From 3eeecb08481a98a61b3e0666a26fe042ab2002ae Mon Sep 17 00:00:00 2001 From: deads2k Date: Tue, 24 Jan 2017 09:25:32 -0500 Subject: [PATCH] preserve client tests that can't move to client-go --- hack/.linted_packages | 2 +- pkg/BUILD | 1 + pkg/client/tests/BUILD | 48 ++++++ pkg/client/tests/doc.go | 18 +++ pkg/client/tests/listwatch_test.go | 228 +++++++++++++++++++++++++++++ staging/copy.sh | 2 - 6 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 pkg/client/tests/BUILD create mode 100644 pkg/client/tests/doc.go create mode 100644 pkg/client/tests/listwatch_test.go diff --git a/hack/.linted_packages b/hack/.linted_packages index 858b6926fda..74ca271f01d 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -86,7 +86,6 @@ pkg/apis/rbac/install pkg/apis/rbac/v1alpha1 pkg/apis/storage/install pkg/apis/storage/validation -pkg/client/cache pkg/client/conditions pkg/client/informers/informers_generated/apps pkg/client/informers/informers_generated/apps/internalversion @@ -297,6 +296,7 @@ staging/src/k8s.io/client-go/plugin/pkg/client/auth staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp staging/src/k8s.io/client-go/rest/watch staging/src/k8s.io/client-go/tools/auth +staging/src/k8s.io/client-go/tools/cache staging/src/k8s.io/client-go/tools/metrics staging/src/k8s.io/client-go/util/cert staging/src/k8s.io/client-go/util/homedir diff --git a/pkg/BUILD b/pkg/BUILD index 64bf426ed52..3bed20e89d5 100644 --- a/pkg/BUILD +++ b/pkg/BUILD @@ -73,6 +73,7 @@ filegroup( "//pkg/client/testdata:all-srcs", "//pkg/client/testing/cache:all-srcs", "//pkg/client/testing/core:all-srcs", + "//pkg/client/tests:all-srcs", "//pkg/client/typed/discovery:all-srcs", "//pkg/client/typed/dynamic:all-srcs", "//pkg/client/unversioned:all-srcs", diff --git a/pkg/client/tests/BUILD b/pkg/client/tests/BUILD new file mode 100644 index 00000000000..e4abe43f5ea --- /dev/null +++ b/pkg/client/tests/BUILD @@ -0,0 +1,48 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["listwatch_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//pkg/api/testapi:go_default_library", + "//pkg/api/v1:go_default_library", + "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apimachinery/pkg/fields", + "//vendor:k8s.io/apimachinery/pkg/runtime", + "//vendor:k8s.io/apimachinery/pkg/watch", + "//vendor:k8s.io/client-go/rest", + "//vendor:k8s.io/client-go/tools/cache", + "//vendor:k8s.io/client-go/util/testing", + ], +) + +go_library( + name = "go_default_library", + srcs = ["doc.go"], + tags = ["automanaged"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/pkg/client/tests/doc.go b/pkg/client/tests/doc.go new file mode 100644 index 00000000000..46cb11fe851 --- /dev/null +++ b/pkg/client/tests/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This package runs tests against the client which require an internal client +package tests diff --git a/pkg/client/tests/listwatch_test.go b/pkg/client/tests/listwatch_test.go new file mode 100644 index 00000000000..18ba412f866 --- /dev/null +++ b/pkg/client/tests/listwatch_test.go @@ -0,0 +1,228 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "net/http/httptest" + "net/url" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + restclient "k8s.io/client-go/rest" + . "k8s.io/client-go/tools/cache" + utiltesting "k8s.io/client-go/util/testing" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/api/v1" + clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" +) + +func parseSelectorOrDie(s string) fields.Selector { + selector, err := fields.ParseSelector(s) + if err != nil { + panic(err) + } + return selector +} + +// buildQueryValues is a convenience function for knowing if a namespace should be in a query param or not +func buildQueryValues(query url.Values) url.Values { + v := url.Values{} + if query != nil { + for key, values := range query { + for _, value := range values { + v.Add(key, value) + } + } + } + return v +} + +func buildLocation(resourcePath string, query url.Values) string { + return resourcePath + "?" + query.Encode() +} + +func TestListWatchesCanList(t *testing.T) { + fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam(api.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()) + table := []struct { + location string + resource string + namespace string + fieldSelector fields.Selector + }{ + // Node + { + location: testapi.Default.ResourcePath("nodes", metav1.NamespaceAll, ""), + resource: "nodes", + namespace: metav1.NamespaceAll, + fieldSelector: parseSelectorOrDie(""), + }, + // pod with "assigned" field selector. + { + location: buildLocation( + testapi.Default.ResourcePath("pods", metav1.NamespaceAll, ""), + buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), + resource: "pods", + namespace: metav1.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) + defer server.Close() + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + lw := NewListWatchFromClient(client.Core().RESTClient(), item.resource, item.namespace, item.fieldSelector) + // This test merely tests that the correct request is made. + lw.List(metav1.ListOptions{}) + handler.ValidateRequest(t, item.location, "GET", nil) + } +} + +func TestListWatchesCanWatch(t *testing.T) { + fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam(api.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()) + table := []struct { + rv string + location string + resource string + namespace string + fieldSelector fields.Selector + }{ + // Node + { + location: buildLocation( + testapi.Default.ResourcePathWithPrefix("watch", "nodes", metav1.NamespaceAll, ""), + buildQueryValues(url.Values{})), + rv: "", + resource: "nodes", + namespace: metav1.NamespaceAll, + fieldSelector: parseSelectorOrDie(""), + }, + { + location: buildLocation( + testapi.Default.ResourcePathWithPrefix("watch", "nodes", metav1.NamespaceAll, ""), + buildQueryValues(url.Values{"resourceVersion": []string{"42"}})), + rv: "42", + resource: "nodes", + namespace: metav1.NamespaceAll, + fieldSelector: parseSelectorOrDie(""), + }, + // pod with "assigned" field selector. + { + location: buildLocation( + testapi.Default.ResourcePathWithPrefix("watch", "pods", metav1.NamespaceAll, ""), + buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})), + rv: "0", + resource: "pods", + namespace: metav1.NamespaceAll, + fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), + }, + // pod with namespace foo and assigned field selector + { + location: buildLocation( + testapi.Default.ResourcePathWithPrefix("watch", "pods", "foo", ""), + buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})), + rv: "0", + 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) + defer server.Close() + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + lw := NewListWatchFromClient(client.Core().RESTClient(), item.resource, item.namespace, item.fieldSelector) + // This test merely tests that the correct request is made. + lw.Watch(metav1.ListOptions{ResourceVersion: item.rv}) + handler.ValidateRequest(t, item.location, "GET", nil) + } +} + +type lw struct { + list runtime.Object + watch watch.Interface +} + +func (w lw) List(options metav1.ListOptions) (runtime.Object, error) { + return w.list, nil +} + +func (w lw) Watch(options metav1.ListOptions) (watch.Interface, error) { + return w.watch, nil +} + +func TestListWatchUntil(t *testing.T) { + fw := watch.NewFake() + go func() { + var obj *v1.Pod + fw.Modify(obj) + }() + listwatch := lw{ + list: &v1.PodList{Items: []v1.Pod{{}}}, + watch: fw, + } + + conditions := []watch.ConditionFunc{ + func(event watch.Event) (bool, error) { + t.Logf("got %#v", event) + return event.Type == watch.Added, nil + }, + func(event watch.Event) (bool, error) { + t.Logf("got %#v", event) + return event.Type == watch.Modified, nil + }, + } + + timeout := 10 * time.Second + lastEvent, err := ListWatchUntil(timeout, listwatch, conditions...) + if err != nil { + t.Fatalf("expected nil error, got %#v", err) + } + if lastEvent == nil { + t.Fatal("expected an event") + } + if lastEvent.Type != watch.Modified { + t.Fatalf("expected MODIFIED event type, got %v", lastEvent.Type) + } + if got, isPod := lastEvent.Object.(*v1.Pod); !isPod { + t.Fatalf("expected a pod event, got %#v", got) + } +} diff --git a/staging/copy.sh b/staging/copy.sh index dcc0b790fcc..da3003686b1 100755 --- a/staging/copy.sh +++ b/staging/copy.sh @@ -92,8 +92,6 @@ function mkcp() { echo "copying client packages" mkcp "pkg/client/clientset_generated/${CLIENTSET}" "pkg/client/clientset_generated" mkcp "/pkg/client/record" "/pkg/client" -# TODO: make this test file not depending on pkg/client/unversioned -rm "${CLIENT_REPO_TEMP}"/pkg/client/cache/listwatch_test.go mkcp "/pkg/client/restclient/fake" "/pkg/client/restclient" mkcp "/pkg/client/testing" "/pkg/client" # remove this test because it imports the internal clientset