Standard input for kubectl tests

rebased to include gobindata as well.
pull/6/head
Jay Vyas 2016-04-26 12:22:18 -04:00
parent 6f288b31cf
commit 801c968fff
6 changed files with 7149 additions and 76 deletions

View File

@ -105,7 +105,8 @@ def file_passes(filename, refs, regexs):
def file_extension(filename):
return os.path.splitext(filename)[1].split(".")[-1].lower()
skipped_dirs = ['vendor', 'third_party', '_gopath', '_output', '.git', 'cluster/env.sh', 'vendor']
skipped_dirs = ['Godeps', 'third_party', '_gopath', '_output', '.git', 'cluster/env.sh', "vendor", "test/e2e/generated/bindata.go"]
def normalize_files(files):
newfiles = []
for pathname in files:

View File

@ -81,7 +81,6 @@ func setupProviderConfig() error {
if cloudConfig.Zone == "" {
return fmt.Errorf("gce-zone must be specified for AWS")
}
}
return nil
@ -227,5 +226,6 @@ func RunE2ETests(t *testing.T) {
}
}
glog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunId, config.GinkgoConfig.ParallelNode)
ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "Kubernetes e2e suite", r)
}

View File

@ -0,0 +1,41 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 framework
import "k8s.io/kubernetes/test/e2e/generated"
// ReadOrDie reads a file from gobindata. To generate gobindata, run
//
// # Install the program
// go get -u github.com/jteeuwen/go-bindata/...
//
// # Generate the bindata file.
// go-bindata \
// -pkg generated -ignore .jpg -ignore .png -ignore .md \
// ./examples/* ./docs/user-guide/* test/e2e/testing-manifests/kubectl/* test/images/*
//
// # Copy it into the generated directory if the results are what you expected.
// cp bindata.go test/e2e/generated
func ReadOrDie(filePath string) []byte {
fileBytes, err := generated.Asset(filePath)
if err != nil {
gobindata_msg := "An error occured, possibly gobindata doesn't know about the file you're opening. For questions on maintaining gobindata, contact the sig-testing group."
Logf("Available gobindata files: %v ", generated.AssetNames())
Failf("Failed opening %v , with error %v. %v.", filePath, err, gobindata_msg)
}
return fileBytes
}

View File

@ -1372,14 +1372,22 @@ func ExpectNoError(err error, explain ...interface{}) {
}
// Stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped.
func Cleanup(filePath string, ns string, selectors ...string) {
func Cleanup(filePath, ns string, selectors ...string) {
By("using delete to clean up resources")
var nsArg string
if ns != "" {
nsArg = fmt.Sprintf("--namespace=%s", ns)
}
RunKubectlOrDie("delete", "--grace-period=0", "-f", filePath, nsArg)
AssertCleanup(ns, selectors...)
}
// Asserts that cleanup of a namespace wrt selectors occured.
func AssertCleanup(ns string, selectors ...string) {
var nsArg string
if ns != "" {
nsArg = fmt.Sprintf("--namespace=%s", ns)
}
for _, selector := range selectors {
resources := RunKubectlOrDie("get", "rc,svc", "-l", selector, "--no-headers", nsArg)
if resources != "" {
@ -1564,8 +1572,8 @@ func RunKubectl(args ...string) (string, error) {
return NewKubectlCommand(args...).Exec()
}
// runKubectlOrDieInput is a convenience wrapper over kubectlBuilder that takes input to stdin
func runKubectlOrDieInput(data string, args ...string) string {
// RunKubectlOrDieInput is a convenience wrapper over kubectlBuilder that takes input to stdin
func RunKubectlOrDieInput(data string, args ...string) string {
return NewKubectlCommand(args...).WithStdinData(data).ExecOrDie()
}

File diff suppressed because one or more lines are too long

View File

@ -115,6 +115,20 @@ var (
podProbeParametersVersion = version.MustParse("v1.2.0-alpha.4")
)
// Stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped.
// Aware of the kubectl example files map.
func cleanupKubectlInputs(fileContents string, ns string, selectors ...string) {
By("using delete to clean up resources")
var nsArg string
if ns != "" {
nsArg = fmt.Sprintf("--namespace=%s", ns)
}
// support backward compatibility : file paths or raw json - since we are removing file path
// dependencies from this test.
framework.RunKubectlOrDieInput(fileContents, "delete", "--grace-period=0", "-f", "-", nsArg)
framework.AssertCleanup(ns, selectors...)
}
var _ = framework.KubeDescribe("Kubectl client", func() {
defer GinkgoRecover()
f := framework.NewDefaultFramework("kubectl")
@ -145,25 +159,25 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
})
framework.KubeDescribe("Update Demo", func() {
var updateDemoRoot, nautilusPath, kittenPath string
var nautilus, kitten []byte
BeforeEach(func() {
updateDemoRoot = filepath.Join(framework.TestContext.RepoRoot, "docs/user-guide/update-demo")
nautilusPath = filepath.Join(updateDemoRoot, "nautilus-rc.yaml")
kittenPath = filepath.Join(updateDemoRoot, "kitten-rc.yaml")
updateDemoRoot := "docs/user-guide/update-demo"
nautilus = framework.ReadOrDie(filepath.Join(updateDemoRoot, "nautilus-rc.yaml"))
kitten = framework.ReadOrDie(filepath.Join(updateDemoRoot, "kitten-rc.yaml"))
})
It("should create and stop a replication controller [Conformance]", func() {
defer framework.Cleanup(nautilusPath, ns, updateDemoSelector)
defer cleanupKubectlInputs(string(nautilus), ns, updateDemoSelector)
By("creating a replication controller")
framework.RunKubectlOrDie("create", "-f", nautilusPath, fmt.Sprintf("--namespace=%v", ns))
framework.RunKubectlOrDieInput(string(nautilus[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
framework.ValidateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
})
It("should scale a replication controller [Conformance]", func() {
defer framework.Cleanup(nautilusPath, ns, updateDemoSelector)
defer cleanupKubectlInputs(string(nautilus[:]), ns, updateDemoSelector)
By("creating a replication controller")
framework.RunKubectlOrDie("create", "-f", nautilusPath, fmt.Sprintf("--namespace=%v", ns))
framework.RunKubectlOrDieInput(string(nautilus[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
framework.ValidateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
By("scaling down the replication controller")
framework.RunKubectlOrDie("scale", "rc", "update-demo-nautilus", "--replicas=1", "--timeout=5m", fmt.Sprintf("--namespace=%v", ns))
@ -175,29 +189,41 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
It("should do a rolling update of a replication controller [Conformance]", func() {
By("creating the initial replication controller")
framework.RunKubectlOrDie("create", "-f", nautilusPath, fmt.Sprintf("--namespace=%v", ns))
framework.RunKubectlOrDieInput(string(nautilus[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
framework.ValidateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
By("rolling-update to new replication controller")
framework.RunKubectlOrDie("rolling-update", "update-demo-nautilus", "--update-period=1s", "-f", kittenPath, fmt.Sprintf("--namespace=%v", ns))
framework.RunKubectlOrDieInput(string(kitten[:]), "rolling-update", "update-demo-nautilus", "--update-period=1s", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
framework.ValidateController(c, kittenImage, 2, "update-demo", updateDemoSelector, getUDData("kitten.jpg", ns), ns)
// Everything will hopefully be cleaned up when the namespace is deleted.
})
})
framework.KubeDescribe("Guestbook application", func() {
var guestbookPath string
BeforeEach(func() {
guestbookPath = filepath.Join(framework.TestContext.RepoRoot, "examples/guestbook")
})
forEachGBFile := func(run func(s string)) {
for _, gbAppFile := range []string{
"examples/guestbook/frontend-deployment.yaml",
"examples/guestbook/frontend-service.yaml",
"examples/guestbook/redis-master-deployment.yaml",
"examples/guestbook/redis-master-service.yaml",
"examples/guestbook/redis-slave-deployment.yaml",
"examples/guestbook/redis-slave-service.yaml",
} {
contents := framework.ReadOrDie(gbAppFile)
run(string(contents))
}
}
It("should create and stop a working application [Conformance]", func() {
framework.SkipUnlessServerVersionGTE(deploymentsVersion, c)
defer framework.Cleanup(guestbookPath, ns, frontendSelector, redisMasterSelector, redisSlaveSelector)
defer forEachGBFile(func(contents string) {
cleanupKubectlInputs(contents, ns)
})
By("creating all guestbook components")
framework.RunKubectlOrDie("create", "-f", guestbookPath, fmt.Sprintf("--namespace=%v", ns))
forEachGBFile(func(contents string) {
framework.Logf(contents)
framework.RunKubectlOrDieInput(contents, "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
})
By("validating guestbook app")
validateGuestbookApp(c, ns)
@ -205,16 +231,16 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
})
framework.KubeDescribe("Simple pod", func() {
var podPath string
var podPath []byte
BeforeEach(func() {
podPath = filepath.Join(framework.TestContext.RepoRoot, "test", "e2e", "testing-manifests", "kubectl", "pod-with-readiness-probe.yaml")
By(fmt.Sprintf("creating the pod from %v", podPath))
framework.RunKubectlOrDie("create", "-f", podPath, fmt.Sprintf("--namespace=%v", ns))
podPath = framework.ReadOrDie("test/e2e/testing-manifests/kubectl/pod-with-readiness-probe.yaml")
By(fmt.Sprintf("creating the pod from %v", string(podPath)))
framework.RunKubectlOrDieInput(string(podPath[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns))
framework.CheckPodsRunningReady(c, ns, []string{simplePodName}, framework.PodStartTimeout)
})
AfterEach(func() {
framework.Cleanup(podPath, ns, simplePodSelector)
cleanupKubectlInputs(string(podPath[:]), ns, simplePodSelector)
})
It("should support exec", func() {
@ -301,8 +327,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.Failf("kube config path could not be accessed. Error=%s", err)
}
// start exec-proxy-tester container
netexecPodPath := filepath.Join(framework.TestContext.RepoRoot, "test/images/netexec/pod.yaml")
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"
@ -313,10 +338,10 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
if !gte {
validateFlag = "--validate=false"
}
framework.RunKubectlOrDie("create", "-f", netexecPodPath, fmt.Sprintf("--namespace=%v", ns), validateFlag)
framework.RunKubectlOrDieInput(string(netexecPod[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns), validateFlag)
framework.CheckPodsRunningReady(c, ns, []string{netexecContainer}, framework.PodStartTimeout)
// Clean up
defer framework.Cleanup(netexecPodPath, ns, netexecPodSelector)
defer cleanupKubectlInputs(string(netexecPod[:]), ns, netexecPodSelector)
defer func() {
if CurrentGinkgoTestDescription().Failed {
logs, err := framework.GetPodLogs(c, ns, "netexec", "netexec")
@ -416,19 +441,21 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.Failf("Unable to upload kubectl binary to remote exec server. /uploads/ not in response. Response: %s", uploadBinaryName)
}
By("Starting goproxy pod")
goproxyPodPath := filepath.Join(framework.TestContext.RepoRoot, "test/images/goproxy/pod.yaml")
framework.RunKubectlOrDie("create", "-f", goproxyPodPath, fmt.Sprintf("--namespace=%v", ns))
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)
// 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)
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)
@ -483,7 +510,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
}
}
// Clean up the goproxyPod
framework.Cleanup(goproxyPodPath, ns, goproxyPodSelector)
cleanupKubectlInputs(string(goproxyPodContents[:]), ns, goproxyPodSelector)
})
It("should support inline execution and attach", func() {
@ -570,14 +597,14 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.KubeDescribe("Kubectl apply", func() {
It("should apply a new configuration to an existing RC", func() {
mkpath := func(file string) string {
return filepath.Join(framework.TestContext.RepoRoot, kubeCtlManifestPath, file)
return "examples/guestbook-go/" + file
}
controllerJson := mkpath("redis-master-controller.json")
controllerJson := framework.ReadOrDie(mkpath("redis-master-controller.json"))
nsFlag := fmt.Sprintf("--namespace=%v", ns)
By("creating Redis RC")
framework.RunKubectlOrDie("create", "-f", controllerJson, nsFlag)
framework.RunKubectlOrDieInput(string(controllerJson), "create", "-f", "-", nsFlag)
By("applying a modified configuration")
stdin := modifyReplicationControllerConfiguration(controllerJson)
stdin := modifyReplicationControllerConfiguration(string(controllerJson))
framework.NewKubectlCommand("apply", "-f", "-", nsFlag).
WithStdinReader(stdin).
ExecOrDie()
@ -586,18 +613,23 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
})
It("should reuse nodePort when apply to an existing SVC", func() {
mkpath := func(file string) string {
return filepath.Join(framework.TestContext.RepoRoot, kubeCtlManifestPath, file)
return "examples/guestbook-go/" + file
}
serviceJson := mkpath("redis-master-service.json")
serviceJson := framework.ReadOrDie(mkpath("redis-master-service.json"))
nsFlag := fmt.Sprintf("--namespace=%v", ns)
By("creating Redis SVC")
framework.RunKubectlOrDie("create", "-f", serviceJson, nsFlag)
framework.RunKubectlOrDieInput(string(serviceJson[:]), "create", "-f", "-", nsFlag)
By("getting the original nodePort")
originalNodePort := framework.RunKubectlOrDie("get", "service", "redis-master", nsFlag, "-o", "jsonpath={.spec.ports[0].nodePort}")
By("applying the same configuration")
framework.RunKubectlOrDie("apply", "-f", serviceJson, nsFlag)
framework.RunKubectlOrDieInput(string(serviceJson[:]), "apply", "-f", "-", nsFlag)
By("getting the nodePort after applying configuration")
currentNodePort := framework.RunKubectlOrDie("get", "service", "redis-master", nsFlag, "-o", "jsonpath={.spec.ports[0].nodePort}")
By("checking the result")
if originalNodePort != currentNodePort {
framework.Failf("nodePort should keep the same")
@ -628,14 +660,14 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.SkipUnlessServerVersionGTE(nodePortsOptionalVersion, c)
mkpath := func(file string) string {
return filepath.Join(framework.TestContext.RepoRoot, kubeCtlManifestPath, file)
return "examples/guestbook-go/" + file
}
controllerJson := mkpath("redis-master-controller.json")
serviceJson := mkpath("redis-master-service.json")
controllerJson := framework.ReadOrDie(mkpath("redis-master-controller.json"))
serviceJson := framework.ReadOrDie(mkpath("redis-master-service.json"))
nsFlag := fmt.Sprintf("--namespace=%v", ns)
framework.RunKubectlOrDie("create", "-f", controllerJson, nsFlag)
framework.RunKubectlOrDie("create", "-f", serviceJson, nsFlag)
framework.RunKubectlOrDieInput(string(controllerJson[:]), "create", "-f", "-", nsFlag)
framework.RunKubectlOrDieInput(string(serviceJson[:]), "create", "-f", "-", nsFlag)
// Wait for the redis pods to come online...
waitFor(1)
@ -730,9 +762,9 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.KubeDescribe("Kubectl expose", func() {
It("should create services for rc [Conformance]", func() {
mkpath := func(file string) string {
return filepath.Join(framework.TestContext.RepoRoot, kubeCtlManifestPath, file)
return "examples/guestbook-go/" + file
}
controllerJson := mkpath("redis-master-controller.json")
controllerJson := framework.ReadOrDie(mkpath("redis-master-controller.json"))
nsFlag := fmt.Sprintf("--namespace=%v", ns)
redisPort := 6379
@ -740,7 +772,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
By("creating Redis RC")
framework.Logf("namespace %v", ns)
framework.RunKubectlOrDie("create", "-f", controllerJson, nsFlag)
framework.RunKubectlOrDieInput(string(controllerJson[:]), "create", "-f", "-", nsFlag)
// It may take a while for the pods to get registered in some cases, wait to be sure.
By("Waiting for Redis master to start.")
@ -805,17 +837,17 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
})
framework.KubeDescribe("Kubectl label", func() {
var podPath string
var pod []byte
var nsFlag string
BeforeEach(func() {
podPath = filepath.Join(framework.TestContext.RepoRoot, "docs/user-guide/pod.yaml")
pod := framework.ReadOrDie("docs/user-guide/pod.yaml")
By("creating the pod")
nsFlag = fmt.Sprintf("--namespace=%v", ns)
framework.RunKubectlOrDie("create", "-f", podPath, nsFlag)
framework.RunKubectlOrDieInput(string(pod), "create", "-f", "-", nsFlag)
framework.CheckPodsRunningReady(c, ns, []string{simplePodName}, framework.PodStartTimeout)
})
AfterEach(func() {
framework.Cleanup(podPath, ns, simplePodSelector)
cleanupKubectlInputs(string(pod[:]), ns, simplePodSelector)
})
It("should update the label on a resource [Conformance]", func() {
@ -841,20 +873,20 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
})
framework.KubeDescribe("Kubectl logs", func() {
var rcPath string
var rc []byte
var nsFlag string
containerName := "redis-master"
BeforeEach(func() {
mkpath := func(file string) string {
return filepath.Join(framework.TestContext.RepoRoot, kubeCtlManifestPath, file)
return "examples/guestbook-go/" + file
}
rcPath = mkpath("redis-master-controller.json")
rc = framework.ReadOrDie(mkpath("redis-master-controller.json"))
By("creating an rc")
nsFlag = fmt.Sprintf("--namespace=%v", ns)
framework.RunKubectlOrDie("create", "-f", rcPath, nsFlag)
framework.RunKubectlOrDieInput(string(rc[:]), "create", "-f", "-", nsFlag)
})
AfterEach(func() {
framework.Cleanup(rcPath, ns, simplePodSelector)
cleanupKubectlInputs(string(rc[:]), ns, simplePodSelector)
})
It("should be able to retrieve and filter logs [Conformance]", func() {
@ -904,12 +936,12 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.KubeDescribe("Kubectl patch", func() {
It("should add annotations for pods in rc [Conformance]", func() {
mkpath := func(file string) string {
return filepath.Join(framework.TestContext.RepoRoot, kubeCtlManifestPath, file)
return "examples/guestbook-go/" + file
}
controllerJson := mkpath("redis-master-controller.json")
controllerJson := framework.ReadOrDie(mkpath("redis-master-controller.json"))
nsFlag := fmt.Sprintf("--namespace=%v", ns)
By("creating Redis RC")
framework.RunKubectlOrDie("create", "-f", controllerJson, nsFlag)
framework.RunKubectlOrDieInput(string(controllerJson[:]), "create", "-f", "-", nsFlag)
By("patching all pods")
forEachPod(func(pod api.Pod) {
framework.RunKubectlOrDie("patch", "pod", pod.Name, nsFlag, "-p", "{\"metadata\":{\"annotations\":{\"x\":\"y\"}}}")
@ -1391,18 +1423,17 @@ func readBytesFromFile(filename string) []byte {
return data
}
func readReplicationControllerFromFile(filename string) *api.ReplicationController {
data := readBytesFromFile(filename)
func readReplicationControllerFromString(contents string) *api.ReplicationController {
rc := api.ReplicationController{}
if err := yaml.Unmarshal(data, &rc); err != nil {
if err := yaml.Unmarshal([]byte(contents), &rc); err != nil {
framework.Failf(err.Error())
}
return &rc
}
func modifyReplicationControllerConfiguration(filename string) io.Reader {
rc := readReplicationControllerFromFile(filename)
func modifyReplicationControllerConfiguration(contents string) io.Reader {
rc := readReplicationControllerFromString(contents)
rc.Labels[applyTestLabel] = "ADDED"
rc.Spec.Selector[applyTestLabel] = "ADDED"
rc.Spec.Template.Labels[applyTestLabel] = "ADDED"