2014-10-23 00:49:40 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors All rights reserved.
|
2014-10-23 00:49:40 +00:00
|
|
|
|
|
|
|
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 (
|
|
|
|
"flag"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
2015-01-04 15:56:20 +00:00
|
|
|
"strconv"
|
2014-10-23 00:49:40 +00:00
|
|
|
"strings"
|
2015-09-15 22:03:34 +00:00
|
|
|
"time"
|
2014-10-23 00:49:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2014-11-11 01:46:11 +00:00
|
|
|
isup = flag.Bool("isup", false, "Check to see if the e2e cluster is up, then exit.")
|
|
|
|
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.")
|
2014-12-08 22:55:47 +00:00
|
|
|
pushup = flag.Bool("pushup", false, "If true, push to e2e cluster if it's up, otherwise start the e2e cluster.")
|
2014-11-11 01:46:11 +00:00
|
|
|
down = flag.Bool("down", false, "If true, tear down the cluster before exiting.")
|
2015-02-05 00:57:53 +00:00
|
|
|
test = flag.Bool("test", false, "Run Ginkgo tests.")
|
2015-02-18 01:39:44 +00:00
|
|
|
testArgs = flag.String("test_args", "", "Space-separated list of arguments to pass to Ginkgo test runner.")
|
2014-11-11 01:46:11 +00:00
|
|
|
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.")
|
|
|
|
checkVersionSkew = flag.Bool("check_version_skew", true, ""+
|
|
|
|
"By default, verify that client and server have exact version match. "+
|
|
|
|
"You can explicitly set to false if you're, e.g., testing client changes "+
|
|
|
|
"for which the server version doesn't make a difference.")
|
2016-05-17 16:11:31 +00:00
|
|
|
checkNodeCount = flag.Bool("check_node_count", true, ""+
|
|
|
|
"By default, verify that the cluster has at least two nodes."+
|
|
|
|
"You can explicitly set to false if you're, e.g., testing single-node clusters "+
|
|
|
|
"for which the node count is supposed to be one.")
|
2014-11-08 00:14:29 +00:00
|
|
|
|
|
|
|
ctlCmd = flag.String("ctl", "", "If nonempty, pass this as an argument, and call kubectl. Implies -v. (-test, -cfg, -ctl are mutually exclusive)")
|
2014-10-23 00:49:40 +00:00
|
|
|
)
|
|
|
|
|
2014-12-16 00:03:11 +00:00
|
|
|
const (
|
2016-02-24 21:08:22 +00:00
|
|
|
minNodeCount = 2
|
2014-12-16 00:03:11 +00:00
|
|
|
)
|
2014-10-23 00:49:40 +00:00
|
|
|
|
|
|
|
func absOrDie(path string) string {
|
|
|
|
out, err := filepath.Abs(path)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
2014-12-08 18:13:37 +00:00
|
|
|
type TestResult struct {
|
|
|
|
Pass int
|
|
|
|
Fail int
|
|
|
|
}
|
|
|
|
|
|
|
|
type ResultsByTest map[string]TestResult
|
|
|
|
|
2014-10-23 00:49:40 +00:00
|
|
|
func main() {
|
2015-09-15 22:03:34 +00:00
|
|
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
2014-10-23 00:49:40 +00:00
|
|
|
flag.Parse()
|
|
|
|
|
2014-10-23 21:47:30 +00:00
|
|
|
if *isup {
|
|
|
|
status := 1
|
2014-12-07 23:29:30 +00:00
|
|
|
if IsUp() {
|
2014-10-23 21:47:30 +00:00
|
|
|
status = 0
|
|
|
|
log.Printf("Cluster is UP")
|
|
|
|
} else {
|
|
|
|
log.Printf("Cluster is DOWN")
|
|
|
|
}
|
|
|
|
os.Exit(status)
|
|
|
|
}
|
|
|
|
|
2014-10-23 00:49:40 +00:00
|
|
|
if *build {
|
2015-02-06 22:33:57 +00:00
|
|
|
// The build-release script needs stdin to ask the user whether
|
|
|
|
// it's OK to download the docker image.
|
|
|
|
cmd := exec.Command(path.Join(*root, "hack/e2e-internal/build-release.sh"))
|
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
if !finishRunning("build-release", cmd) {
|
2014-10-23 00:49:40 +00:00
|
|
|
log.Fatal("Error building. Aborting.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-24 21:08:22 +00:00
|
|
|
os.Setenv("KUBECTL", *root+`/cluster/kubectl.sh`+kubectlArgs())
|
2015-02-05 08:00:28 +00:00
|
|
|
|
2014-12-08 22:55:47 +00:00
|
|
|
if *pushup {
|
|
|
|
if IsUp() {
|
|
|
|
log.Printf("e2e cluster is up, pushing.")
|
|
|
|
*up = false
|
|
|
|
*push = true
|
|
|
|
} else {
|
|
|
|
log.Printf("e2e cluster is down, creating.")
|
|
|
|
*up = true
|
|
|
|
*push = false
|
|
|
|
}
|
|
|
|
}
|
2014-10-23 00:49:40 +00:00
|
|
|
if *up {
|
|
|
|
if !Up() {
|
|
|
|
log.Fatal("Error starting e2e cluster. Aborting.")
|
|
|
|
}
|
|
|
|
} else if *push {
|
2015-02-06 22:33:57 +00:00
|
|
|
if !finishRunning("push", exec.Command(path.Join(*root, "hack/e2e-internal/e2e-push.sh"))) {
|
2014-10-23 00:49:40 +00:00
|
|
|
log.Fatal("Error pushing e2e cluster. Aborting.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-11 21:11:03 +00:00
|
|
|
success := true
|
2014-11-08 00:14:29 +00:00
|
|
|
switch {
|
|
|
|
case *ctlCmd != "":
|
2015-02-06 22:33:57 +00:00
|
|
|
ctlArgs := strings.Fields(*ctlCmd)
|
2015-02-06 22:27:59 +00:00
|
|
|
os.Setenv("KUBE_CONFIG_FILE", "config-test.sh")
|
2016-02-24 21:08:22 +00:00
|
|
|
success = finishRunning("'kubectl "+*ctlCmd+"'", exec.Command(path.Join(*root, "cluster/kubectl.sh"), ctlArgs...))
|
2015-02-05 00:57:53 +00:00
|
|
|
case *test:
|
2015-02-11 21:11:03 +00:00
|
|
|
success = Test()
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if *down {
|
|
|
|
TearDown()
|
|
|
|
}
|
|
|
|
|
2015-02-11 21:11:03 +00:00
|
|
|
if !success {
|
2014-10-23 00:49:40 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-14 23:57:28 +00:00
|
|
|
func TearDown() bool {
|
2015-02-06 22:33:57 +00:00
|
|
|
return finishRunning("teardown", exec.Command(path.Join(*root, "hack/e2e-internal/e2e-down.sh")))
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
|
|
|
|
2015-01-14 23:57:28 +00:00
|
|
|
// Up brings an e2e cluster up, recreating it if one is already running.
|
2014-10-23 00:49:40 +00:00
|
|
|
func Up() bool {
|
2015-01-14 23:57:28 +00:00
|
|
|
if IsUp() {
|
|
|
|
log.Printf("e2e cluster already running; will teardown")
|
|
|
|
if res := TearDown(); !res {
|
|
|
|
return false
|
|
|
|
}
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
2015-02-06 22:33:57 +00:00
|
|
|
return finishRunning("up", exec.Command(path.Join(*root, "hack/e2e-internal/e2e-up.sh")))
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
|
|
|
|
2015-01-16 00:43:03 +00:00
|
|
|
// Ensure that the cluster is large engough to run the e2e tests.
|
|
|
|
func ValidateClusterSize() {
|
2016-05-10 21:44:45 +00:00
|
|
|
if os.Getenv("FEDERATION") == "true" {
|
|
|
|
//TODO(colhom): federated equivalent of ValidateClusterSize
|
|
|
|
return
|
|
|
|
}
|
2015-11-30 22:31:32 +00:00
|
|
|
// Check that there are at least minNodeCount nodes running
|
2015-02-11 22:57:34 +00:00
|
|
|
cmd := exec.Command(path.Join(*root, "hack/e2e-internal/e2e-cluster-size.sh"))
|
|
|
|
if *verbose {
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
}
|
|
|
|
stdout, err := cmd.Output()
|
|
|
|
if err != nil {
|
2015-05-10 04:08:55 +00:00
|
|
|
log.Fatalf("Could not get nodes to validate cluster size (%s)", err)
|
2015-01-16 00:43:03 +00:00
|
|
|
}
|
|
|
|
|
2015-02-11 22:57:34 +00:00
|
|
|
numNodes, err := strconv.Atoi(strings.TrimSpace(string(stdout)))
|
2015-01-16 00:43:03 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Could not count number of nodes to validate cluster size (%s)", err)
|
|
|
|
}
|
|
|
|
|
2015-11-30 22:31:32 +00:00
|
|
|
if numNodes < minNodeCount {
|
|
|
|
log.Fatalf("Cluster size (%d) is too small to run e2e tests. %d Nodes are required.", numNodes, minNodeCount)
|
2015-01-16 00:43:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-07 23:29:30 +00:00
|
|
|
// Is the e2e cluster up?
|
|
|
|
func IsUp() bool {
|
2015-02-06 22:33:57 +00:00
|
|
|
return finishRunning("get status", exec.Command(path.Join(*root, "hack/e2e-internal/e2e-status.sh")))
|
2014-12-07 23:29:30 +00:00
|
|
|
}
|
|
|
|
|
2015-02-05 00:57:53 +00:00
|
|
|
func Test() bool {
|
2014-12-07 23:29:30 +00:00
|
|
|
if !IsUp() {
|
|
|
|
log.Fatal("Testing requested, but e2e cluster not up!")
|
|
|
|
}
|
|
|
|
|
2016-05-17 16:11:31 +00:00
|
|
|
if *checkNodeCount {
|
|
|
|
ValidateClusterSize()
|
|
|
|
}
|
2015-01-16 00:43:03 +00:00
|
|
|
|
2016-05-10 21:44:45 +00:00
|
|
|
if os.Getenv("FEDERATION") == "" {
|
|
|
|
return finishRunning("Ginkgo tests", exec.Command(filepath.Join(*root, "hack/ginkgo-e2e.sh"), strings.Fields(*testArgs)...))
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if *testArgs == "" {
|
|
|
|
*testArgs = "--ginkgo.focus=\\[Feature:Federation\\]"
|
|
|
|
}
|
|
|
|
return finishRunning("Federated Ginkgo tests", exec.Command(filepath.Join(*root, "hack/federated-ginkgo-e2e.sh"), strings.Fields(*testArgs)...))
|
|
|
|
}
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 21:53:27 +00:00
|
|
|
func finishRunning(stepName string, cmd *exec.Cmd) bool {
|
2014-10-23 00:49:40 +00:00
|
|
|
if *verbose {
|
2015-02-13 21:53:27 +00:00
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
cmd.Stderr = os.Stderr
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
2015-02-13 21:53:27 +00:00
|
|
|
log.Printf("Running: %v", stepName)
|
2015-09-15 22:03:34 +00:00
|
|
|
defer func(start time.Time) {
|
|
|
|
log.Printf("Step '%s' finished in %s", stepName, time.Since(start))
|
|
|
|
}(time.Now())
|
|
|
|
|
2014-10-23 00:49:40 +00:00
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
log.Printf("Error running %v: %v", stepName, err)
|
2015-02-13 21:53:27 +00:00
|
|
|
return false
|
2014-10-23 00:49:40 +00:00
|
|
|
}
|
2015-02-13 21:53:27 +00:00
|
|
|
return true
|
2015-02-06 22:33:57 +00:00
|
|
|
}
|
|
|
|
|
2014-11-12 21:30:53 +00:00
|
|
|
// returns either "", or a list of args intended for appending with the
|
2015-08-08 21:29:57 +00:00
|
|
|
// kubectl command (beginning with a space).
|
2014-11-12 21:30:53 +00:00
|
|
|
func kubectlArgs() string {
|
2016-05-10 21:44:45 +00:00
|
|
|
args := []string{""}
|
2014-11-12 21:30:53 +00:00
|
|
|
if *checkVersionSkew {
|
2016-05-10 21:44:45 +00:00
|
|
|
args = append(args, "--match-server-version")
|
2014-11-12 21:30:53 +00:00
|
|
|
}
|
2016-05-10 21:44:45 +00:00
|
|
|
return strings.Join(args, " ")
|
2014-11-12 21:30:53 +00:00
|
|
|
}
|