Removing indirection from proxy exec test

I removed the netexec and goproxy pods from the proxy exec test. Instead
it now runs kubectl locally and the proxy is running in-process. Since
Go won't proxy for localhost requests, this test cannot pass if the API
server is local. However it was already disabled for local clusters.
pull/6/head
Kris 2016-05-17 14:56:27 -07:00
parent 2c471bce4e
commit f4cf45ee94
2 changed files with 28 additions and 214 deletions

View File

@ -1615,6 +1615,11 @@ func NewKubectlCommand(args ...string) *kubectlBuilder {
return b
}
func (b *kubectlBuilder) WithEnv(env []string) *kubectlBuilder {
b.cmd.Env = env
return b
}
func (b *kubectlBuilder) WithTimeout(t <-chan time.Time) *kubectlBuilder {
b.timeout = t
return b

View File

@ -23,10 +23,11 @@ import (
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net"
"net/http"
"net/url"
"net/http/httptest"
"os"
"os/exec"
"path"
@ -37,6 +38,7 @@ import (
"strings"
"time"
"github.com/elazarl/goproxy"
"github.com/ghodss/yaml"
"k8s.io/kubernetes/pkg/api"
@ -298,233 +300,32 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.Failf("--host variable must be set to the full URI to the api server on e2e run.")
}
// Make sure the apiServer is set to what kubectl requires
apiServer := framework.TestContext.Host
apiServerUrl, err := url.Parse(apiServer)
if err != nil {
framework.Failf("Unable to parse URL %s. Error=%s", apiServer, err)
}
apiServerUrl.Scheme = "https"
if !strings.Contains(apiServer, ":443") {
apiServerUrl.Host = apiServerUrl.Host + ":443"
}
apiServer = apiServerUrl.String()
// Build the static kubectl
By("Finding a static kubectl for upload")
testStaticKubectlPath, err := findBinary("kubectl", "linux/amd64")
if err != nil {
framework.Logf("No kubectl found: %v.\nAttempting a local build...", err)
// Fall back to trying to build a local static kubectl
kubectlContainerPath := path.Join(framework.TestContext.RepoRoot, "/examples/kubectl-container/")
if _, err := os.Stat(path.Join(framework.TestContext.RepoRoot, "hack/build-go.sh")); err != nil {
framework.Failf("Can't build static kubectl due to missing hack/build-go.sh. Error=%s", err)
}
By("Building a static kubectl for upload")
staticKubectlBuild := exec.Command("make", "-C", kubectlContainerPath)
if out, err := staticKubectlBuild.Output(); err != nil {
framework.Failf("Unable to create static kubectl. Error=%s, Output=%q", err, out)
}
// Verify the static kubectl path
testStaticKubectlPath = path.Join(kubectlContainerPath, "kubectl")
_, err := os.Stat(testStaticKubectlPath)
if err != nil {
framework.Failf("static kubectl path could not be found in %s. Error=%s", testStaticKubectlPath, err)
}
}
By(fmt.Sprintf("Using the kubectl in %s", testStaticKubectlPath))
// Verify the kubeconfig path
kubeConfigFilePath := framework.TestContext.KubeConfig
_, err = os.Stat(kubeConfigFilePath)
if err != nil {
framework.Failf("kube config path could not be accessed. Error=%s", err)
}
// start exec-proxy-tester container
netexecPod := framework.ReadOrDie("test/images/netexec/pod.yaml")
// Add "validate=false" if the server version is less than 1.2.
// More details: https://github.com/kubernetes/kubernetes/issues/22884.
validateFlag := "--validate=true"
gte, err := framework.ServerVersionGTE(podProbeParametersVersion, c)
if err != nil {
framework.Failf("Failed to get server version: %v", err)
}
if !gte {
validateFlag = "--validate=false"
}
framework.RunKubectlOrDieInput(string(netexecPod[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns), validateFlag)
framework.CheckPodsRunningReady(c, ns, []string{netexecContainer}, framework.PodStartTimeout)
// Clean up
defer cleanupKubectlInputs(string(netexecPod[:]), ns, netexecPodSelector)
defer func() {
if CurrentGinkgoTestDescription().Failed {
logs, err := framework.GetPodLogs(c, ns, "netexec", "netexec")
framework.Logf("Logs for netexec pod(error: %s): %s", err, logs)
}
}()
// Upload kubeconfig
type NetexecOutput struct {
Output string `json:"output"`
Error string `json:"error"`
}
var uploadConfigOutput NetexecOutput
// Upload the kubeconfig file
By("uploading kubeconfig to netexec")
pipeConfigReader, postConfigBodyWriter, err := newStreamingUpload(kubeConfigFilePath)
if err != nil {
framework.Failf("unable to create streaming upload. Error: %s", err)
}
subResourceProxyAvailable, err := framework.ServerVersionGTE(framework.SubResourcePodProxyVersion, c)
if err != nil {
framework.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 {
framework.Failf("Unable to upload kubeconfig to the remote exec server due to error: %s", err)
}
if err := json.Unmarshal(resp, &uploadConfigOutput); err != nil {
framework.Failf("Unable to read the result from the netexec server. Error: %s", err)
}
kubecConfigRemotePath := uploadConfigOutput.Output
// Upload
pipeReader, postBodyWriter, err := newStreamingUpload(testStaticKubectlPath)
if err != nil {
framework.Failf("unable to create streaming upload. Error: %s", err)
}
By("uploading kubectl to netexec")
var uploadOutput NetexecOutput
// Upload the kubectl binary
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 {
framework.Failf("Unable to upload kubectl binary to the remote exec server due to error: %s", err)
}
if err := json.Unmarshal(resp, &uploadOutput); err != nil {
framework.Failf("Unable to read the result from the netexec server. Error: %s", err)
}
uploadBinaryName := uploadOutput.Output
// Verify that we got the expected response back in the body
if !strings.HasPrefix(uploadBinaryName, "/uploads/") {
framework.Failf("Unable to upload kubectl binary to remote exec server. /uploads/ not in response. Response: %s", uploadBinaryName)
}
By("Starting goproxy pods using different strategies.")
goproxyPodContents := framework.ReadOrDie("test/images/goproxy/pod.yaml")
framework.RunKubectlOrDieInput(string(goproxyPodContents[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
framework.CheckPodsRunningReady(c, ns, []string{goproxyContainer}, framework.PodStartTimeout)
By("Starting goproxy")
testSrv, proxyLogs := startLocalProxy()
defer testSrv.Close()
proxyAddr := testSrv.URL
for _, proxyVar := range []string{"https_proxy", "HTTPS_PROXY"} {
By("Running kubectl in netexec via an HTTP proxy using " + proxyVar)
// get the proxy address
goproxyPod, err := c.Pods(ns).Get(goproxyContainer)
if err != nil {
framework.Failf("Unable to get the goproxy pod. Error: %s", err)
}
proxyAddr := fmt.Sprintf("http://%s:8080", goproxyPod.Status.PodIP)
By("Running kubectl in netexec via an HTTP proxy using " + proxyVar)
shellCommand := fmt.Sprintf("%s=%s .%s --kubeconfig=%s --server=%s --namespace=%s exec nginx echo running in container",
proxyVar, proxyAddr, uploadBinaryName, kubecConfigRemotePath, apiServer, ns)
framework.Logf("About to remote exec: %v", shellCommand)
// Execute kubectl on remote exec server.
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 {
framework.Failf("Unable to execute kubectl binary on the remote exec server due to error: %s", err)
}
var netexecOuput NetexecOutput
if err := json.Unmarshal(netexecShellOutput, &netexecOuput); err != nil {
framework.Failf("Unable to read the result from the netexec server. Error: %s", err)
}
// Get (and print!) the proxy logs here, so
// they'll be present in case the below check
// fails the test, to help diagnose #19500 if
// it recurs.
proxyLog := framework.RunKubectlOrDie("log", "goproxy", fmt.Sprintf("--namespace=%v", ns))
proxyLogs.Reset()
By("Running kubectl via an HTTP proxy using " + proxyVar)
output := framework.NewKubectlCommand(fmt.Sprintf("--namespace=%s", ns), "exec", "nginx", "echo", "running", "in", "container").
WithEnv(append(os.Environ(), fmt.Sprintf("%s=%s", proxyVar, proxyAddr))).
ExecOrDie()
// Verify we got the normal output captured by the exec server
expectedExecOutput := "running in container\n"
if netexecOuput.Output != expectedExecOutput {
framework.Failf("Unexpected kubectl exec output. Wanted %q, got %q", expectedExecOutput, netexecOuput.Output)
if output != expectedExecOutput {
framework.Failf("Unexpected kubectl exec output. Wanted %q, got %q", expectedExecOutput, output)
}
// Verify the proxy server logs saw the connection
expectedProxyLog := fmt.Sprintf("Accepting CONNECT to %s", strings.TrimRight(strings.TrimLeft(framework.TestContext.Host, "https://"), "/api"))
proxyLog := proxyLogs.String()
if !strings.Contains(proxyLog, expectedProxyLog) {
framework.Failf("Missing expected log result on proxy server for %s. Expected: %q, got %q", proxyVar, expectedProxyLog, proxyLog)
}
}
// Clean up the goproxyPod
cleanupKubectlInputs(string(goproxyPodContents[:]), ns, goproxyPodSelector)
})
It("should support inline execution and attach", func() {
@ -1656,3 +1457,11 @@ func findBinary(binName string, platform string) (string, error) {
}
return binPath, fmt.Errorf("Could not find %v for %v", binName, platform)
}
func startLocalProxy() (srv *httptest.Server, logs *bytes.Buffer) {
logs = &bytes.Buffer{}
p := goproxy.NewProxyHttpServer()
p.Verbose = true
p.Logger = log.New(logs, "", 0)
return httptest.NewServer(p), logs
}