diff --git a/test/e2e/framework/BUILD b/test/e2e/framework/BUILD index 6454e47c13d..455c1491de3 100644 --- a/test/e2e/framework/BUILD +++ b/test/e2e/framework/BUILD @@ -72,6 +72,7 @@ go_library( "//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//test/e2e/framework/auth:go_default_library", "//test/e2e/framework/ginkgowrapper:go_default_library", + "//test/e2e/framework/kubectl:go_default_library", "//test/e2e/framework/metrics:go_default_library", "//test/e2e/framework/node:go_default_library", "//test/e2e/framework/pod:go_default_library", diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index a0343f2ce10..918e0cf715c 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -52,6 +52,7 @@ import ( "github.com/onsi/gomega" // TODO: Remove the following imports (ref: https://github.com/kubernetes/kubernetes/issues/81245) + e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" e2emetrics "k8s.io/kubernetes/test/e2e/framework/metrics" e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" @@ -702,7 +703,8 @@ func kubectlExec(namespace string, podName, containerName string, args ...string } cmdArgs = append(cmdArgs, args...) - cmd := KubectlCmd(cmdArgs...) + tk := e2ekubectl.NewTestKubeconfig(TestContext.CertDir, TestContext.Host, TestContext.KubeConfig, TestContext.KubeContext, TestContext.KubectlPath) + cmd := tk.KubectlCmd(cmdArgs...) cmd.Stdout, cmd.Stderr = &stdout, &stderr Logf("Running '%s %s'", cmd.Path, strings.Join(cmdArgs, " ")) diff --git a/test/e2e/framework/kubectl/BUILD b/test/e2e/framework/kubectl/BUILD index c093865db1f..d97b35ea1c0 100644 --- a/test/e2e/framework/kubectl/BUILD +++ b/test/e2e/framework/kubectl/BUILD @@ -9,6 +9,7 @@ go_library( "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", + "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e/framework/pod:go_default_library", "//test/utils:go_default_library", diff --git a/test/e2e/framework/kubectl/kubectl_utils.go b/test/e2e/framework/kubectl/kubectl_utils.go index c11b59e60cf..e46da16fabf 100644 --- a/test/e2e/framework/kubectl/kubectl_utils.go +++ b/test/e2e/framework/kubectl/kubectl_utils.go @@ -17,16 +17,74 @@ limitations under the License. package kubectl import ( + "fmt" + "os/exec" + "path/filepath" "strings" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" testutils "k8s.io/kubernetes/test/utils" ) +// TestKubeconfig is a struct containing the minimum attributes needed to run KubectlCmd. +type TestKubeconfig struct { + CertDir string + Host string + KubeConfig string + KubeContext string + KubectlPath string +} + +// NewTestKubeconfig returns a new Kubeconfig struct instance. +func NewTestKubeconfig(certdir string, host string, kubeconfig string, kubecontext string, kubectlpath string) *TestKubeconfig { + return &TestKubeconfig{ + CertDir: certdir, + Host: host, + KubeConfig: kubeconfig, + KubeContext: kubecontext, + KubectlPath: kubectlpath, + } +} + +// KubectlCmd runs the kubectl executable through the wrapper script. +func (tk *TestKubeconfig) KubectlCmd(args ...string) *exec.Cmd { + defaultArgs := []string{} + + // Reference a --server option so tests can run anywhere. + if tk.Host != "" { + defaultArgs = append(defaultArgs, "--"+clientcmd.FlagAPIServer+"="+tk.Host) + } + if tk.KubeConfig != "" { + defaultArgs = append(defaultArgs, "--"+clientcmd.RecommendedConfigPathFlag+"="+tk.KubeConfig) + + // Reference the KubeContext + if tk.KubeContext != "" { + defaultArgs = append(defaultArgs, "--"+clientcmd.FlagContext+"="+tk.KubeContext) + } + + } else { + if tk.CertDir != "" { + defaultArgs = append(defaultArgs, + fmt.Sprintf("--certificate-authority=%s", filepath.Join(tk.CertDir, "ca.crt")), + fmt.Sprintf("--client-certificate=%s", filepath.Join(tk.CertDir, "kubecfg.crt")), + fmt.Sprintf("--client-key=%s", filepath.Join(tk.CertDir, "kubecfg.key"))) + } + } + kubectlArgs := append(defaultArgs, args...) + + //We allow users to specify path to kubectl, so you can test either "kubectl" or "cluster/kubectl.sh" + //and so on. + cmd := exec.Command(tk.KubectlPath, kubectlArgs...) + + //caller will invoke this and wait on it. + return cmd +} + // LogFailedContainers runs `kubectl logs` on a failed containers. func LogFailedContainers(c clientset.Interface, ns string, logFunc func(ftm string, args ...interface{})) { podList, err := c.CoreV1().Pods(ns).List(metav1.ListOptions{}) diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index a9235bcced5..ae463ad1abc 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -75,6 +75,7 @@ import ( uexec "k8s.io/utils/exec" // TODO: Remove the following imports (ref: https://github.com/kubernetes/kubernetes/issues/81245) + e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" e2emetrics "k8s.io/kubernetes/test/e2e/framework/metrics" e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" @@ -620,40 +621,6 @@ func AssertCleanup(ns string, selectors ...string) { } } -// KubectlCmd runs the kubectl executable through the wrapper script. -func KubectlCmd(args ...string) *exec.Cmd { - defaultArgs := []string{} - - // Reference a --server option so tests can run anywhere. - if TestContext.Host != "" { - defaultArgs = append(defaultArgs, "--"+clientcmd.FlagAPIServer+"="+TestContext.Host) - } - if TestContext.KubeConfig != "" { - defaultArgs = append(defaultArgs, "--"+clientcmd.RecommendedConfigPathFlag+"="+TestContext.KubeConfig) - - // Reference the KubeContext - if TestContext.KubeContext != "" { - defaultArgs = append(defaultArgs, "--"+clientcmd.FlagContext+"="+TestContext.KubeContext) - } - - } else { - if TestContext.CertDir != "" { - defaultArgs = append(defaultArgs, - fmt.Sprintf("--certificate-authority=%s", filepath.Join(TestContext.CertDir, "ca.crt")), - fmt.Sprintf("--client-certificate=%s", filepath.Join(TestContext.CertDir, "kubecfg.crt")), - fmt.Sprintf("--client-key=%s", filepath.Join(TestContext.CertDir, "kubecfg.key"))) - } - } - kubectlArgs := append(defaultArgs, args...) - - //We allow users to specify path to kubectl, so you can test either "kubectl" or "cluster/kubectl.sh" - //and so on. - cmd := exec.Command(TestContext.KubectlPath, kubectlArgs...) - - //caller will invoke this and wait on it. - return cmd -} - // LookForStringInPodExec looks for the given string in the output of a command // executed in a specific pod container. // TODO(alejandrox1): move to pod/ subpkg once kubectl methods are refactored. @@ -691,7 +658,8 @@ type KubectlBuilder struct { // NewKubectlCommand returns a KubectlBuilder for running kubectl. func NewKubectlCommand(args ...string) *KubectlBuilder { b := new(KubectlBuilder) - b.cmd = KubectlCmd(args...) + tk := e2ekubectl.NewTestKubeconfig(TestContext.CertDir, TestContext.Host, TestContext.KubeConfig, TestContext.KubeContext, TestContext.KubectlPath) + b.cmd = tk.KubectlCmd(args...) return b } diff --git a/test/e2e/kubectl/BUILD b/test/e2e/kubectl/BUILD index 32717ed6a20..6d2faae79cb 100644 --- a/test/e2e/kubectl/BUILD +++ b/test/e2e/kubectl/BUILD @@ -42,6 +42,7 @@ go_library( "//test/e2e/framework/auth:go_default_library", "//test/e2e/framework/endpoints:go_default_library", "//test/e2e/framework/job:go_default_library", + "//test/e2e/framework/kubectl:go_default_library", "//test/e2e/framework/pod:go_default_library", "//test/e2e/framework/service:go_default_library", "//test/e2e/framework/testfiles:go_default_library", diff --git a/test/e2e/kubectl/kubectl.go b/test/e2e/kubectl/kubectl.go index aeb0b1e0ff5..930e3bddb4d 100644 --- a/test/e2e/kubectl/kubectl.go +++ b/test/e2e/kubectl/kubectl.go @@ -70,6 +70,7 @@ import ( "k8s.io/kubernetes/test/e2e/framework/auth" e2eendpoints "k8s.io/kubernetes/test/e2e/framework/endpoints" jobutil "k8s.io/kubernetes/test/e2e/framework/job" + e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2eservice "k8s.io/kubernetes/test/e2e/framework/service" "k8s.io/kubernetes/test/e2e/framework/testfiles" @@ -1993,7 +1994,8 @@ metadata: path := filepath.Join(tmpdir, "test") defer os.Remove(path) defer os.Remove(tmpdir) - cmd := framework.KubectlCmd("proxy", fmt.Sprintf("--unix-socket=%s", path)) + tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath) + cmd := tk.KubectlCmd("proxy", fmt.Sprintf("--unix-socket=%s", path)) stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd) if err != nil { framework.Failf("Failed to start kubectl command: %v", err) @@ -2249,7 +2251,8 @@ func getAPIVersions(apiEndpoint string) (*metav1.APIVersions, error) { func startProxyServer() (int, *exec.Cmd, error) { // Specifying port 0 indicates we want the os to pick a random port. - cmd := framework.KubectlCmd("proxy", "-p", "0", "--disable-filter") + tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath) + cmd := tk.KubectlCmd("proxy", "-p", "0", "--disable-filter") stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd) if err != nil { return -1, nil, err diff --git a/test/e2e/kubectl/portforward.go b/test/e2e/kubectl/portforward.go index e4b60ac618b..e87f0cc3f3e 100644 --- a/test/e2e/kubectl/portforward.go +++ b/test/e2e/kubectl/portforward.go @@ -36,6 +36,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/test/e2e/framework" + e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" testutils "k8s.io/kubernetes/test/utils" imageutils "k8s.io/kubernetes/test/utils/image" @@ -168,7 +169,8 @@ func (c *portForwardCommand) Stop() { // runPortForward runs port-forward, warning, this may need root functionality on some systems. func runPortForward(ns, podName string, port int) *portForwardCommand { - cmd := framework.KubectlCmd("port-forward", fmt.Sprintf("--namespace=%v", ns), podName, fmt.Sprintf(":%d", port)) + tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath) + cmd := tk.KubectlCmd("port-forward", fmt.Sprintf("--namespace=%v", ns), podName, fmt.Sprintf(":%d", port)) // This is somewhat ugly but is the only way to retrieve the port that was picked // by the port-forward command. We don't want to hard code the port as we have no // way of guaranteeing we can pick one that isn't in use, particularly on Jenkins. diff --git a/test/e2e/node/pods.go b/test/e2e/node/pods.go index 71bdfc90f48..22673e0bfd1 100644 --- a/test/e2e/node/pods.go +++ b/test/e2e/node/pods.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/test/e2e/framework" + e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" e2ekubelet "k8s.io/kubernetes/test/e2e/framework/kubelet" imageutils "k8s.io/kubernetes/test/utils/image" diff --git a/test/e2e/windows/BUILD b/test/e2e/windows/BUILD index 4732b8e856f..31f949b4e7b 100644 --- a/test/e2e/windows/BUILD +++ b/test/e2e/windows/BUILD @@ -36,6 +36,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/kubelet/config/v1beta1:go_default_library", "//test/e2e/framework:go_default_library", + "//test/e2e/framework/kubectl:go_default_library", "//test/e2e/framework/metrics:go_default_library", "//test/e2e/framework/network:go_default_library", "//test/e2e/framework/node:go_default_library", diff --git a/test/e2e/windows/memory_limits.go b/test/e2e/windows/memory_limits.go index 9093d5d7f6b..b52e6f53679 100644 --- a/test/e2e/windows/memory_limits.go +++ b/test/e2e/windows/memory_limits.go @@ -35,6 +35,7 @@ import ( kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1" kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" "k8s.io/kubernetes/test/e2e/framework" + e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" imageutils "k8s.io/kubernetes/test/utils/image" "github.com/onsi/ginkgo" @@ -263,7 +264,8 @@ func getCurrentKubeletConfig(nodeName string) (*kubeletconfig.KubeletConfigurati func pollConfigz(timeout time.Duration, pollInterval time.Duration, nodeName string) *http.Response { // start local proxy, so we can send graceful deletion over query string, rather than body parameter ginkgo.By("Opening proxy to cluster") - cmd := framework.KubectlCmd("proxy", "-p", "0") + tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath) + cmd := tk.KubectlCmd("proxy", "-p", "0") stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd) framework.ExpectNoError(err) defer stdout.Close()