mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
Merge pull request #1968 from lavalamp/fix4
New e2e script (in go this time) that doesn't completely suck
This commit is contained in:
commit
edf729ce71
@ -34,6 +34,7 @@ server_targets=(
|
|||||||
client_targets=(
|
client_targets=(
|
||||||
cmd/kubecfg
|
cmd/kubecfg
|
||||||
cmd/kubectl
|
cmd/kubectl
|
||||||
|
cmd/e2e
|
||||||
)
|
)
|
||||||
|
|
||||||
mkdir -p "${KUBE_TARGET}"
|
mkdir -p "${KUBE_TARGET}"
|
||||||
|
@ -518,7 +518,6 @@ function test-build-release {
|
|||||||
#
|
#
|
||||||
# Assumed vars:
|
# Assumed vars:
|
||||||
# PROJECT
|
# PROJECT
|
||||||
# ALREADY_UP
|
|
||||||
# Variables from config.sh
|
# Variables from config.sh
|
||||||
function test-setup {
|
function test-setup {
|
||||||
|
|
||||||
@ -526,7 +525,6 @@ function test-setup {
|
|||||||
# gce specific
|
# gce specific
|
||||||
detect-project
|
detect-project
|
||||||
|
|
||||||
if [[ ${ALREADY_UP} -ne 1 ]]; then
|
|
||||||
# Open up port 80 & 8080 so common containers on minions can be reached
|
# Open up port 80 & 8080 so common containers on minions can be reached
|
||||||
gcutil addfirewall \
|
gcutil addfirewall \
|
||||||
--project "${PROJECT}" \
|
--project "${PROJECT}" \
|
||||||
@ -536,8 +534,6 @@ function test-setup {
|
|||||||
--allowed tcp:80,tcp:8080 \
|
--allowed tcp:80,tcp:8080 \
|
||||||
--network "${NETWORK}" \
|
--network "${NETWORK}" \
|
||||||
"${MINION_TAG}-${INSTANCE_PREFIX}-http-alt"
|
"${MINION_TAG}-${INSTANCE_PREFIX}-http-alt"
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Execute after running tests to perform any required clean-up. This is called
|
# Execute after running tests to perform any required clean-up. This is called
|
||||||
|
@ -14,88 +14,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Starts a Kubernetes cluster, runs the e2e test suite, and shuts it
|
# Provided for backwards compatibility
|
||||||
# down.
|
go run e2e.go -v -build -up -tests="*" -down
|
||||||
#
|
|
||||||
# Environment flags:
|
|
||||||
# TEST_PATTERN: A pattern to match test filenames against.
|
|
||||||
# Example: "TEST_PATTERN=up" would match tests named "update.sh" and
|
|
||||||
# "hiccup.sh".
|
|
||||||
|
|
||||||
set -o errexit
|
exit $?
|
||||||
set -o nounset
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
# Use testing config
|
|
||||||
export KUBE_CONFIG_FILE="config-test.sh"
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
|
||||||
|
|
||||||
# TODO(jbeda): This will break on usage if there is a space in
|
|
||||||
# ${KUBE_ROOT}. Covert to an array? Or an exported function?
|
|
||||||
export KUBECFG="${KUBE_ROOT}/cluster/kubecfg.sh -expect_version_match"
|
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
|
||||||
|
|
||||||
# For debugging of this test's components, it's helpful to leave the test
|
|
||||||
# cluster running.
|
|
||||||
ALREADY_UP=${1:-0}
|
|
||||||
LEAVE_UP=${2:-0}
|
|
||||||
TEAR_DOWN=${3:-0}
|
|
||||||
|
|
||||||
if [[ $TEAR_DOWN -ne 0 ]]; then
|
|
||||||
detect-project
|
|
||||||
trap test-teardown EXIT
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build a release required by the test provider [if any]
|
|
||||||
test-build-release
|
|
||||||
|
|
||||||
if [[ ${ALREADY_UP} -ne 1 ]]; then
|
|
||||||
# Now bring a test cluster up with that release.
|
|
||||||
"${KUBE_ROOT}/cluster/kube-up.sh"
|
|
||||||
else
|
|
||||||
# Just push instead
|
|
||||||
"${KUBE_ROOT}/cluster/kube-push.sh"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Perform any required setup of the cluster
|
|
||||||
test-setup
|
|
||||||
|
|
||||||
set +e
|
|
||||||
|
|
||||||
if [[ ${LEAVE_UP} -ne 1 ]]; then
|
|
||||||
trap test-teardown EXIT
|
|
||||||
fi
|
|
||||||
|
|
||||||
TEST_PATTERN="${TEST_PATTERN:-}"
|
|
||||||
failed=()
|
|
||||||
for test_file in $(ls "${KUBE_ROOT}/hack/e2e-suite/"); do
|
|
||||||
if [[ "${TEST_PATTERN}" != "" ]]; then
|
|
||||||
check=".*${TEST_PATTERN}.*"
|
|
||||||
if [[ ! "$test_file" =~ $check ]]; then
|
|
||||||
echo "skipping $test_file"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "+++ Running $test_file"
|
|
||||||
result=0
|
|
||||||
"${KUBE_ROOT}/hack/e2e-suite/${test_file}" || result="$?"
|
|
||||||
if [[ "${result}" -eq "0" ]]; then
|
|
||||||
echo "${test_file} returned ${result}; passed!"
|
|
||||||
else
|
|
||||||
echo "${test_file} returned ${result}; FAIL!"
|
|
||||||
failed+=(${test_file})
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo
|
|
||||||
if [[ "${#failed[*]}" -eq 0 ]]; then
|
|
||||||
echo "Final: All tests passed."
|
|
||||||
else
|
|
||||||
echo "Final: ${#failed[@]} tests failed: ${failed[@]}."
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit "${#failed[@]}"
|
|
||||||
|
203
hack/e2e.go
Normal file
203
hack/e2e.go
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Google Inc. 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// e2e.go runs the e2e test suite. No non-standard package dependencies; call with "go run".
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
build = flag.Bool("build", false, "If true, build a new release. Otherwise, use whatever is there.")
|
||||||
|
up = flag.Bool("up", false, "If true, start the the e2e cluster. If cluster is already up, recreate it.")
|
||||||
|
push = flag.Bool("push", false, "If true, push to e2e cluster. Has no effect if -up is true.")
|
||||||
|
down = flag.Bool("down", false, "If true, tear down the cluster before exiting.")
|
||||||
|
tests = flag.String("tests", "*", "Run tests in hack/e2e-suite matching this glob.")
|
||||||
|
root = flag.String("root", absOrDie(filepath.Clean(filepath.Join(path.Base(os.Args[0]), ".."))), "Root directory of kubernetes repository.")
|
||||||
|
verbose = flag.Bool("v", false, "If true, print all command output.")
|
||||||
|
)
|
||||||
|
|
||||||
|
var signals = make(chan os.Signal, 100)
|
||||||
|
|
||||||
|
func absOrDie(path string) string {
|
||||||
|
out, err := filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
signal.Notify(signals, os.Interrupt)
|
||||||
|
|
||||||
|
if *build {
|
||||||
|
if runBash("build", `test-build-release`) {
|
||||||
|
log.Fatal("Error building. Aborting.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if *up {
|
||||||
|
if !Up() {
|
||||||
|
log.Fatal("Error starting e2e cluster. Aborting.")
|
||||||
|
}
|
||||||
|
} else if *push {
|
||||||
|
if !runBash("push", path.Join(*root, "/cluster/kube-push.sh")) {
|
||||||
|
log.Fatal("Error pushing e2e cluster. Aborting.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
failed, passed := []string{}, []string{}
|
||||||
|
if *tests != "" {
|
||||||
|
failed, passed = Test()
|
||||||
|
}
|
||||||
|
|
||||||
|
if *down {
|
||||||
|
TearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Passed tests: %v", passed)
|
||||||
|
log.Printf("Failed tests: %v", failed)
|
||||||
|
if len(failed) > 0 {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TearDown() {
|
||||||
|
runBash("teardown", "test-teardown")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Up() bool {
|
||||||
|
if !tryUp() {
|
||||||
|
log.Printf("kube-up failed; will tear down and retry. (Possibly your cluster was in some partially created state?)")
|
||||||
|
TearDown()
|
||||||
|
return tryUp()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryUp() bool {
|
||||||
|
return runBash("up", path.Join(*root, "/cluster/kube-up.sh; test-setup;"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test() (failed, passed []string) {
|
||||||
|
// run tests!
|
||||||
|
dir, err := os.Open(filepath.Join(*root, "hack", "e2e-suite"))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Couldn't open e2e-suite dir")
|
||||||
|
}
|
||||||
|
defer dir.Close()
|
||||||
|
names, err := dir.Readdirnames(0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Couldn't read names in e2e-suite dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range names {
|
||||||
|
name := names[i]
|
||||||
|
if name == "." || name == ".." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if match, err := path.Match(*tests, name); !match && err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
absName := filepath.Join(*root, "hack", "e2e-suite", name)
|
||||||
|
log.Printf("%v matches %v. Starting test.", name, *tests)
|
||||||
|
if runBash(name, absName) {
|
||||||
|
log.Printf("%v passed", name)
|
||||||
|
passed = append(passed, name)
|
||||||
|
} else {
|
||||||
|
log.Printf("%v failed", name)
|
||||||
|
failed = append(failed, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// All nonsense below is temporary until we have go versions of these things.
|
||||||
|
|
||||||
|
func runBash(stepName, bashFragment string) bool {
|
||||||
|
log.Printf("Running: %v", stepName)
|
||||||
|
cmd := exec.Command("bash", "-s")
|
||||||
|
cmd.Stdin = strings.NewReader(bashWrap(bashFragment))
|
||||||
|
stdout, stderr := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
|
||||||
|
if *verbose {
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
} else {
|
||||||
|
cmd.Stdout = stdout
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
case s := <-signals:
|
||||||
|
cmd.Process.Signal(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
log.Printf("Error running %v: %v", stepName, err)
|
||||||
|
if !*verbose {
|
||||||
|
fmt.Printf("stdout:\n------\n%v\n------\n", string(stdout.Bytes()))
|
||||||
|
fmt.Printf("stderr:\n------\n%v\n------\n", string(stderr.Bytes()))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var bashCommandPrefix = `
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
export KUBE_CONFIG_FILE="config-test.sh"
|
||||||
|
|
||||||
|
# TODO(jbeda): This will break on usage if there is a space in
|
||||||
|
# ${KUBE_ROOT}. Covert to an array? Or an exported function?
|
||||||
|
export KUBECFG="` + *root + `/cluster/kubecfg.sh -expect_version_match"
|
||||||
|
|
||||||
|
source "` + *root + `/cluster/kube-env.sh"
|
||||||
|
source "` + *root + `/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
detect-project
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
var bashCommandSuffix = `
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
func bashWrap(cmd string) string {
|
||||||
|
return bashCommandPrefix + cmd + bashCommandSuffix
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user