diff --git a/pkg/version/semver.go b/pkg/version/semver.go index 3d18a10209c..1b5a845ad28 100644 --- a/pkg/version/semver.go +++ b/pkg/version/semver.go @@ -44,7 +44,7 @@ func Parse(gitversion string) (semver.Version, error) { func MustParse(gitversion string) semver.Version { v, err := Parse(gitversion) if err != nil { - glog.Fatalf("failed to parse semver from giversion %q: %v", gitversion, err) + glog.Fatalf("failed to parse semver from gitversion %q: %v", gitversion, err) } return v } diff --git a/test/e2e/dns.go b/test/e2e/dns.go index 2425190e660..356188b4bc8 100644 --- a/test/e2e/dns.go +++ b/test/e2e/dns.go @@ -130,14 +130,29 @@ func assertFilesExist(fileNames []string, fileDir string, pod *api.Pod, client * expectNoError(wait.Poll(time.Second*2, time.Second*60, func() (bool, error) { failed = []string{} + subResourceProxyAvailable, err := serverVersionGTE(subResourceProxyVersion, client) + if err != nil { + return false, err + } for _, fileName := range fileNames { - if _, err := client.Get(). - Namespace(pod.Namespace). - Resource("pods"). - SubResource("proxy"). - Name(pod.Name). - Suffix(fileDir, fileName). - Do().Raw(); err != nil { + if subResourceProxyAvailable { + _, err = client.Get(). + Namespace(pod.Namespace). + Resource("pods"). + SubResource("proxy"). + Name(pod.Name). + Suffix(fileDir, fileName). + Do().Raw() + } else { + _, err = client.Get(). + Prefix("proxy"). + Resource("pods"). + Namespace(pod.Namespace). + Name(pod.Name). + Suffix(fileDir, fileName). + Do().Raw() + } + if err != nil { Logf("Unable to read %s from pod %s: %v", fileName, pod.Name, err) failed = append(failed, fileName) } diff --git a/test/e2e/kubectl.go b/test/e2e/kubectl.go index 264b4d6bb20..55a85cc2196 100644 --- a/test/e2e/kubectl.go +++ b/test/e2e/kubectl.go @@ -258,15 +258,34 @@ var _ = Describe("Kubectl client", func() { if err != nil { Failf("unable to create streaming upload. Error: %s", err) } - resp, err := c.Post(). - Namespace(ns). - Name("netexec"). - Resource("pods"). - SubResource("proxy"). - Suffix("upload"). - SetHeader("Content-Type", postConfigBodyWriter.FormDataContentType()). - Body(pipeConfigReader). - Do().Raw() + + subResourceProxyAvailable, err := serverVersionGTE(subResourceProxyVersion, c) + if err != nil { + Failf("Unable to determine server version. Error: %s", err) + } + + var resp []byte + if subResourceProxyAvailable { + resp, err = c.Post(). + Namespace(ns). + Name("netexec"). + Resource("pods"). + SubResource("proxy"). + Suffix("upload"). + SetHeader("Content-Type", postConfigBodyWriter.FormDataContentType()). + Body(pipeConfigReader). + Do().Raw() + } else { + resp, err = c.Post(). + Prefix("proxy"). + Namespace(ns). + Name("netexec"). + Resource("pods"). + Suffix("upload"). + SetHeader("Content-Type", postConfigBodyWriter.FormDataContentType()). + Body(pipeConfigReader). + Do().Raw() + } if err != nil { Failf("Unable to upload kubeconfig to the remote exec server due to error: %s", err) } @@ -285,15 +304,27 @@ var _ = Describe("Kubectl client", func() { By("uploading kubectl to netexec") var uploadOutput NetexecOutput // Upload the kubectl binary - resp, err = c.Post(). - Namespace(ns). - Name("netexec"). - Resource("pods"). - SubResource("proxy"). - Suffix("upload"). - SetHeader("Content-Type", postBodyWriter.FormDataContentType()). - Body(pipeReader). - Do().Raw() + if subResourceProxyAvailable { + resp, err = c.Post(). + Namespace(ns). + Name("netexec"). + Resource("pods"). + SubResource("proxy"). + Suffix("upload"). + SetHeader("Content-Type", postBodyWriter.FormDataContentType()). + Body(pipeReader). + Do().Raw() + } else { + resp, err = c.Post(). + Prefix("proxy"). + Namespace(ns). + Name("netexec"). + Resource("pods"). + Suffix("upload"). + SetHeader("Content-Type", postBodyWriter.FormDataContentType()). + Body(pipeReader). + Do().Raw() + } if err != nil { Failf("Unable to upload kubectl binary to the remote exec server due to error: %s", err) } @@ -323,14 +354,26 @@ var _ = Describe("Kubectl client", func() { shellCommand := fmt.Sprintf("%s=%s .%s --kubeconfig=%s --server=%s --namespace=%s exec nginx echo running in container", proxyVar, proxyAddr, uploadBinaryName, kubecConfigRemotePath, apiServer, ns) // Execute kubectl on remote exec server. - netexecShellOutput, err := c.Post(). - Namespace(ns). - Name("netexec"). - Resource("pods"). - SubResource("proxy"). - Suffix("shell"). - Param("shellCommand", shellCommand). - Do().Raw() + var netexecShellOutput []byte + if subResourceProxyAvailable { + netexecShellOutput, err = c.Post(). + Namespace(ns). + Name("netexec"). + Resource("pods"). + SubResource("proxy"). + Suffix("shell"). + Param("shellCommand", shellCommand). + Do().Raw() + } else { + netexecShellOutput, err = c.Post(). + Prefix("proxy"). + Namespace(ns). + Name("netexec"). + Resource("pods"). + Suffix("shell"). + Param("shellCommand", shellCommand). + Do().Raw() + } if err != nil { Failf("Unable to execute kubectl binary on the remote exec server due to error: %s", err) } @@ -1145,14 +1188,30 @@ func getUDData(jpgExpected string, ns string) func(*client.Client, string) error // getUDData validates data.json in the update-demo (returns nil if data is ok). return func(c *client.Client, podID string) error { Logf("validating pod %s", podID) - body, err := c.Get(). - Namespace(ns). - Resource("pods"). - SubResource("proxy"). - Name(podID). - Suffix("data.json"). - Do(). - Raw() + subResourceProxyAvailable, err := serverVersionGTE(subResourceProxyVersion, c) + if err != nil { + return err + } + var body []byte + if subResourceProxyAvailable { + body, err = c.Get(). + Namespace(ns). + Resource("pods"). + SubResource("proxy"). + Name(podID). + Suffix("data.json"). + Do(). + Raw() + } else { + body, err = c.Get(). + Prefix("proxy"). + Namespace(ns). + Resource("pods"). + Name(podID). + Suffix("data.json"). + Do(). + Raw() + } if err != nil { return err } diff --git a/test/e2e/pre_stop.go b/test/e2e/pre_stop.go index 4cd93838ab7..e34860bce6a 100644 --- a/test/e2e/pre_stop.go +++ b/test/e2e/pre_stop.go @@ -117,13 +117,29 @@ func testPreStop(c *client.Client, ns string) { // Validate that the server received the web poke. err = wait.Poll(time.Second*5, time.Second*60, func() (bool, error) { - if body, err := c.Get(). - Namespace(ns). - Resource("pods"). - SubResource("proxy"). - Name(podDescr.Name). - Suffix("read"). - DoRaw(); err != nil { + subResourceProxyAvailable, err := serverVersionGTE(subResourceProxyVersion, c) + if err != nil { + return false, err + } + var body []byte + if subResourceProxyAvailable { + body, err = c.Get(). + Namespace(ns). + Resource("pods"). + SubResource("proxy"). + Name(podDescr.Name). + Suffix("read"). + DoRaw() + } else { + body, err = c.Get(). + Prefix("proxy"). + Namespace(ns). + Resource("pods"). + Name(podDescr.Name). + Suffix("read"). + DoRaw() + } + if err != nil { By(fmt.Sprintf("Error validating prestop: %v", err)) } else { Logf("Saw: %s", string(body)) diff --git a/test/e2e/util.go b/test/e2e/util.go index bc3bbd08433..d355ba83ea5 100644 --- a/test/e2e/util.go +++ b/test/e2e/util.go @@ -52,8 +52,10 @@ import ( deploymentutil "k8s.io/kubernetes/pkg/util/deployment" "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/wait" + "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/watch" + "github.com/blang/semver" "github.com/davecgh/go-spew/spew" "golang.org/x/crypto/ssh" "golang.org/x/net/websocket" @@ -106,6 +108,14 @@ const ( endpointRegisterTimeout = time.Minute ) +// SubResource proxy should have been functional in v1.0.0, but SubResource +// proxy via tunneling is known to be broken in v1.0. See +// https://github.com/kubernetes/kubernetes/pull/15224#issuecomment-146769463 +// +// TODO(ihmccreery): remove once we don't care about v1.0 anymore, (tentatively +// in v1.3). +var subResourceProxyVersion = version.MustParse("v1.1.0") + type CloudConfig struct { ProjectID string Zone string @@ -899,13 +909,28 @@ func (r podResponseChecker) checkAllResponses() (done bool, err error) { if !isElementOf(pod.UID, currentPods) { return false, fmt.Errorf("pod with UID %s is no longer a member of the replica set. Must have been restarted for some reason. Current replica set: %v", pod.UID, currentPods) } - body, err := r.c.Get(). - Namespace(r.ns). - Resource("pods"). - SubResource("proxy"). - Name(string(pod.Name)). - Do(). - Raw() + subResourceProxyAvailable, err := serverVersionGTE(subResourceProxyVersion, r.c) + if err != nil { + return false, err + } + var body []byte + if subResourceProxyAvailable { + body, err = r.c.Get(). + Namespace(r.ns). + Resource("pods"). + SubResource("proxy"). + Name(string(pod.Name)). + Do(). + Raw() + } else { + body, err = r.c.Get(). + Prefix("proxy"). + Namespace(r.ns). + Resource("pods"). + Name(string(pod.Name)). + Do(). + Raw() + } if err != nil { Logf("Controller %s: Failed to GET from replica %d [%s]: %v:", r.controllerName, i+1, pod.Name, err) continue @@ -940,6 +965,22 @@ func (r podResponseChecker) checkAllResponses() (done bool, err error) { return true, nil } +// serverVersionGTE returns true if v is greater than or equal to the server +// version. +// +// TODO(18726): This should be incorporated into client.VersionInterface. +func serverVersionGTE(v semver.Version, c client.VersionInterface) (bool, error) { + serverVersion, err := c.ServerVersion() + if err != nil { + return false, fmt.Errorf("Unable to get server version: %v", err) + } + sv, err := version.Parse(serverVersion.GitVersion) + if err != nil { + return false, fmt.Errorf("Unable to parse server version %q: %v", serverVersion.GitVersion, err) + } + return sv.GTE(v), nil +} + func podsResponding(c *client.Client, ns, name string, wantName bool, pods *api.PodList) error { By("trying to dial each unique pod") label := labels.SelectorFromSet(labels.Set(map[string]string{"name": name})) diff --git a/test/e2e/volumes.go b/test/e2e/volumes.go index 60d302367bb..b16a725d7f6 100644 --- a/test/e2e/volumes.go +++ b/test/e2e/volumes.go @@ -225,12 +225,26 @@ func testVolumeClient(client *client.Client, config VolumeTestConfig, volume api expectNoError(waitForPodRunningInNamespace(client, clientPod.Name, config.namespace)) By("reading a web page from the client") - body, err := client.Get(). - Namespace(config.namespace). - Resource("pods"). - SubResource("proxy"). - Name(clientPod.Name). - DoRaw() + subResourceProxyAvailable, err := serverVersionGTE(subResourceProxyVersion, client) + if err != nil { + Failf("Failed to get server version: %v", err) + } + var body []byte + if subResourceProxyAvailable { + body, err = client.Get(). + Namespace(config.namespace). + Resource("pods"). + SubResource("proxy"). + Name(clientPod.Name). + DoRaw() + } else { + body, err = client.Get(). + Prefix("proxy"). + Namespace(config.namespace). + Resource("pods"). + Name(clientPod.Name). + DoRaw() + } expectNoError(err, "Cannot read web page: %v", err) Logf("body: %v", string(body))