From 51c0271e0a29dc76c12e020f0936a6df199cc923 Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Fri, 5 Aug 2016 23:00:12 -0700 Subject: [PATCH] added a e2e test that uses the staged client; made necessary changes to gcp auth plugin to pass the gke tests --- plugin/pkg/client/auth/gcp/gcp.go | 13 ++++++ test/e2e/e2e.go | 6 +-- test/e2e/framework/framework.go | 42 +++++++++++++++++++- test/e2e/generated_clientset.go | 66 +++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 4 deletions(-) diff --git a/plugin/pkg/client/auth/gcp/gcp.go b/plugin/pkg/client/auth/gcp/gcp.go index 32cbb362550..fa5e079f6b5 100644 --- a/plugin/pkg/client/auth/gcp/gcp.go +++ b/plugin/pkg/client/auth/gcp/gcp.go @@ -25,6 +25,7 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" + clientreporestclient "k8s.io/client-go/1.4/rest" "k8s.io/kubernetes/pkg/client/restclient" ) @@ -32,6 +33,9 @@ func init() { if err := restclient.RegisterAuthProviderPlugin("gcp", newGCPAuthProvider); err != nil { glog.Fatalf("Failed to register gcp auth plugin: %v", err) } + if err := clientreporestclient.RegisterAuthProviderPlugin("gcp", newGCPAuthProviderForClientRepo); err != nil { + glog.Fatalf("Failed to register gcp auth plugin: %v", err) + } } type gcpAuthProvider struct { @@ -47,6 +51,15 @@ func newGCPAuthProvider(_ string, gcpConfig map[string]string, persister restcli return &gcpAuthProvider{ts, persister}, nil } +// newGCPAuthProviderForClientRepo is the same as newGCPAuthProvider, but is programmed against client-go's interface +func newGCPAuthProviderForClientRepo(_ string, gcpConfig map[string]string, persister clientreporestclient.AuthProviderConfigPersister) (clientreporestclient.AuthProvider, error) { + ts, err := newCachedTokenSource(gcpConfig["access-token"], gcpConfig["expiry"], persister) + if err != nil { + return nil, err + } + return &gcpAuthProvider{ts, persister}, nil +} + func (g *gcpAuthProvider) WrapTransport(rt http.RoundTripper) http.RoundTripper { return &oauth2.Transport{ Source: g.tokenSource, diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index ecde2c6ea51..8e52612e75a 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -32,7 +32,7 @@ import ( "k8s.io/kubernetes/pkg/api" gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" - "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/runtime" commontest "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" @@ -215,8 +215,8 @@ var _ = ginkgo.SynchronizedAfterSuite(func() { // This function is called on each Ginkgo node in parallel mode. func RunE2ETests(t *testing.T) { runtime.ReallyCrash = true - util.InitLogs() - defer util.FlushLogs() + logs.InitLogs() + defer logs.FlushLogs() gomega.RegisterFailHandler(ginkgo.Fail) // Disable skipped tests unless they are explicitly requested. diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index bedc2374ad5..654327fa44f 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -18,6 +18,7 @@ package framework import ( "bytes" + "encoding/json" "fmt" "io/ioutil" "reflect" @@ -25,6 +26,9 @@ import ( "sync" "time" + release_1_4 "k8s.io/client-go/1.4/kubernetes" + "k8s.io/client-go/1.4/pkg/util/sets" + clientreporestclient "k8s.io/client-go/1.4/rest" "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset" unversionedfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/unversioned" "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_3" @@ -33,6 +37,7 @@ import ( apierrs "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" + "k8s.io/kubernetes/pkg/client/restclient" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" @@ -57,6 +62,7 @@ type Framework struct { Client *client.Client Clientset_1_2 *release_1_2.Clientset Clientset_1_3 *release_1_3.Clientset + StagingClient *release_1_4.Clientset // TODO(mml): Remove this. We should generally use the versioned clientset. FederationClientset *federation_internalclientset.Clientset @@ -131,6 +137,38 @@ func NewFramework(baseName string, options FrameworkOptions, client *client.Clie return f } +// getClientRepoConfig copies k8s.io/kubernetes/pkg/client/restclient.Config to +// a k8s.io/client-go/pkg/client/restclient.Config. It's not a deep copy. Two +// configs may share some common struct. +func getClientRepoConfig(src *restclient.Config) (dst *clientreporestclient.Config) { + skippedFields := sets.NewString("Transport", "WrapTransport", "RateLimiter", "AuthConfigPersister") + dst = &clientreporestclient.Config{} + dst.Transport = src.Transport + dst.WrapTransport = src.WrapTransport + dst.RateLimiter = src.RateLimiter + dst.AuthConfigPersister = src.AuthConfigPersister + sv := reflect.ValueOf(src).Elem() + dv := reflect.ValueOf(dst).Elem() + for i := 0; i < sv.NumField(); i++ { + if skippedFields.Has(sv.Type().Field(i).Name) { + continue + } + sf := sv.Field(i).Interface() + data, err := json.Marshal(sf) + if err != nil { + Expect(err).NotTo(HaveOccurred()) + } + if !dv.Field(i).CanAddr() { + Failf("unaddressable field: %v", dv.Type().Field(i).Name) + } else { + if err := json.Unmarshal(data, dv.Field(i).Addr().Interface()); err != nil { + Expect(err).NotTo(HaveOccurred()) + } + } + } + return dst +} + // BeforeEach gets a client and makes a namespace. func (f *Framework) BeforeEach() { // The fact that we need this feels like a bug in ginkgo. @@ -149,9 +187,11 @@ func (f *Framework) BeforeEach() { Expect(err).NotTo(HaveOccurred()) f.Client = c f.Clientset_1_2, err = release_1_2.NewForConfig(config) - Expect(err).NotTo(HaveOccurred()) f.Clientset_1_3, err = release_1_3.NewForConfig(config) Expect(err).NotTo(HaveOccurred()) + clientRepoConfig := getClientRepoConfig(config) + f.StagingClient, err = release_1_4.NewForConfig(clientRepoConfig) + Expect(err).NotTo(HaveOccurred()) } if f.federated { diff --git a/test/e2e/generated_clientset.go b/test/e2e/generated_clientset.go index 2ca552ce268..8027e40dcce 100644 --- a/test/e2e/generated_clientset.go +++ b/test/e2e/generated_clientset.go @@ -20,12 +20,15 @@ import ( "strconv" "time" + clientapi "k8s.io/client-go/1.4/pkg/api" + clientv1 "k8s.io/client-go/1.4/pkg/api/v1" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/uuid" + "k8s.io/kubernetes/pkg/util/wait" "k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/test/e2e/framework" @@ -33,6 +36,27 @@ import ( . "github.com/onsi/gomega" ) +func stagingClientPod(name, value string) clientv1.Pod { + return clientv1.Pod{ + ObjectMeta: clientv1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "name": "foo", + "time": value, + }, + }, + Spec: clientv1.PodSpec{ + Containers: []clientv1.Container{ + { + Name: "nginx", + Image: "gcr.io/google_containers/nginx-slim:0.7", + Ports: []clientv1.ContainerPort{{ContainerPort: 80}}, + }, + }, + }, + } +} + func testingPod(name, value string) v1.Pod { return v1.Pod{ ObjectMeta: v1.ObjectMeta{ @@ -242,3 +266,45 @@ var _ = framework.KubeDescribe("Generated release_1_3 clientset", func() { Expect(len(pods.Items)).To(Equal(0)) }) }) + +var _ = framework.KubeDescribe("Staging client repo client", func() { + f := framework.NewDefaultFramework("clientset") + It("should create pods, delete pods, watch pods", func() { + podClient := f.StagingClient.Core().Pods(f.Namespace.Name) + By("constructing the pod") + name := "pod" + string(uuid.NewUUID()) + value := strconv.Itoa(time.Now().Nanosecond()) + podCopy := stagingClientPod(name, value) + pod := &podCopy + By("verifying no pod exists before the test") + pods, err := podClient.List(clientapi.ListOptions{}) + if err != nil { + framework.Failf("Failed to query for pods: %v", err) + } + Expect(len(pods.Items)).To(Equal(0)) + By("creating the pod") + pod, err = podClient.Create(pod) + if err != nil { + framework.Failf("Failed to create pod: %v", err) + } + // We call defer here in case there is a problem with + // the test so we can ensure that we clean up after + // ourselves + defer podClient.Delete(pod.Name, clientapi.NewDeleteOptions(0)) + + By("verifying the pod is in kubernetes") + timeout := 1 * time.Minute + if err := wait.PollImmediate(time.Second, timeout, func() (bool, error) { + pods, err = podClient.List(clientapi.ListOptions{}) + if err != nil { + return false, err + } + if len(pods.Items) == 1 { + return true, nil + } + return false, nil + }); err != nil { + framework.Failf("Err : %s\n. Failed to wait for 1 pod to be created", err) + } + }) +})