minikube/test/integration/version_upgrade_test.go

253 lines
8.3 KiB
Go
Raw Normal View History

/*
Copyright 2019 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 integration
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"runtime"
"testing"
2019-07-24 20:32:32 +00:00
"time"
"k8s.io/minikube/pkg/minikube/constants"
2019-08-14 05:18:47 +00:00
"k8s.io/minikube/pkg/util/retry"
2019-07-26 17:00:51 +00:00
"github.com/hashicorp/go-getter"
pkgutil "k8s.io/minikube/pkg/util"
)
2019-06-12 17:44:04 +00:00
func installRelease(version string) (f *os.File, err error) {
tf, err := ioutil.TempFile("", fmt.Sprintf("minikube-%s.*.exe", version))
if err != nil {
return tf, err
}
tf.Close()
url := pkgutil.GetBinaryDownloadURL(version, runtime.GOOS)
if err := retry.Expo(func() error { return getter.GetFile(tf.Name(), url) }, 3*time.Second, Minutes(3)); err != nil {
return tf, err
}
if runtime.GOOS != "windows" {
if err := os.Chmod(tf.Name(), 0700); err != nil {
return tf, err
}
}
2020-07-17 00:34:46 +00:00
return tf, nil
}
// TestRunningBinaryUpgrade does an upgrade test on a running cluster
func TestRunningBinaryUpgrade(t *testing.T) {
MaybeParallel(t)
2020-07-17 00:34:46 +00:00
profile := UniqueProfileName("binary-upgrade")
2020-02-21 00:19:59 +00:00
ctx, cancel := context.WithTimeout(context.Background(), Minutes(55))
2019-07-26 17:00:51 +00:00
defer CleanupWithLogs(t, profile, cancel)
// Should be a version from the last 6 months
legacyVersion := "v1.6.2"
if KicDriver() {
// v1.8.0 would be selected, but: https://github.com/kubernetes/minikube/issues/8740
legacyVersion = "v1.9.0"
2020-07-17 00:34:46 +00:00
}
tf, err := installRelease(legacyVersion)
if err != nil {
t.Fatalf("%s release installation failed: %v", legacyVersion, err)
}
defer os.Remove(tf.Name())
args := append([]string{"start", "-p", profile, "--memory=2200"}, StartArgs()...)
rr := &RunResult{}
r := func() error {
rr, err = Run(t, exec.CommandContext(ctx, tf.Name(), args...))
return err
}
// Retry up to two times, to allow flakiness for the legacy release
if err := retry.Expo(r, 1*time.Second, Minutes(30), 2); err != nil {
t.Fatalf("legacy %s start failed: %v", legacyVersion, err)
}
args = append([]string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=1"}, StartArgs()...)
rr, err = Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
t.Fatalf("upgrade from %s to HEAD failed: %s: %v", legacyVersion, rr.Command(), err)
}
}
// TestStoppedBinaryUpgrade does an upgrade test on a stopped cluster
func TestStoppedBinaryUpgrade(t *testing.T) {
MaybeParallel(t)
profile := UniqueProfileName("binary-upgrade")
ctx, cancel := context.WithTimeout(context.Background(), Minutes(55))
defer CleanupWithLogs(t, profile, cancel)
// Guarantee stopped upgrade compatibility from a release that is at least 1 year old
// NOTE: <v1.4.0 does not automatically install a hyperkit/KVM driver
legacyVersion := "v1.0.0"
if KicDriver() {
// first release with non-experimental KIC
legacyVersion = "v1.8.0"
}
tf, err := installRelease(legacyVersion)
if err != nil {
t.Fatalf("%s release installation failed: %v", legacyVersion, err)
}
defer os.Remove(tf.Name())
2020-07-17 00:34:46 +00:00
args := append([]string{"start", "-p", profile, "--memory=2200"}, StartArgs()...)
rr := &RunResult{}
r := func() error {
rr, err = Run(t, exec.CommandContext(ctx, tf.Name(), args...))
return err
}
// Retry up to two times, to allow flakiness for the legacy release
2020-03-24 13:29:35 +00:00
if err := retry.Expo(r, 1*time.Second, Minutes(30), 2); err != nil {
t.Fatalf("legacy %s start failed: %v", legacyVersion, err)
}
rr, err = Run(t, exec.CommandContext(ctx, tf.Name(), "-p", profile, "stop"))
if err != nil {
t.Errorf("failed to stop cluster: %s: %v", rr.Command(), err)
}
2020-07-17 00:34:46 +00:00
args = append([]string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=1"}, StartArgs()...)
rr, err = Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
t.Fatalf("upgrade from %s to HEAD failed: %s: %v", legacyVersion, rr.Command(), err)
}
2020-07-17 00:34:46 +00:00
}
// TestKubernetesUpgrade upgrades Kubernetes from oldest to newest
2020-07-17 00:34:46 +00:00
func TestKubernetesUpgrade(t *testing.T) {
MaybeParallel(t)
profile := UniqueProfileName("kubernetes-upgrade")
2020-07-17 00:34:46 +00:00
ctx, cancel := context.WithTimeout(context.Background(), Minutes(55))
defer CleanupWithLogs(t, profile, cancel)
args := append([]string{"start", "-p", profile, "--memory=2200", fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion), "--alsologtostderr", "-v=1"}, StartArgs()...)
rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
2020-07-17 00:34:46 +00:00
t.Errorf("failed to start minikube HEAD with oldest k8s version: %s: %v", rr.Command(), err)
}
2020-07-17 00:34:46 +00:00
rr, err = Run(t, exec.CommandContext(ctx, Target(), "stop"))
if err != nil {
t.Errorf("failed to stop cluster: %s: %v", rr.Command(), err)
}
args = append([]string{"start", "-p", profile, "--memory=2200", fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion), "--alsologtostderr", "-v=1"}, StartArgs()...)
rr, err = Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
2020-07-17 00:34:46 +00:00
t.Errorf("failed to upgrade with newest k8s version. args: %s : %v", rr.Command(), err)
}
s, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "version", "--output=json"))
if err != nil {
t.Fatalf("error running kubectl: %v", err)
}
cv := struct {
ServerVersion struct {
GitVersion string `json:"gitVersion"`
} `json:"serverVersion"`
}{}
err = json.Unmarshal(s.Stdout.Bytes(), &cv)
if err != nil {
t.Fatalf("error traversing json output: %v", err)
}
if cv.ServerVersion.GitVersion != constants.NewestKubernetesVersion {
t.Fatalf("expected server version %s is not the same with latest version %s", cv.ServerVersion.GitVersion, constants.NewestKubernetesVersion)
}
t.Logf("Attempting to downgrade Kubernetes (should fail)")
args = append([]string{"start", "-p", profile, "--memory=2200", fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion)}, StartArgs()...)
2020-07-17 00:34:46 +00:00
if rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)); err == nil {
t.Fatalf("downgrading Kubernetes should not be allowed. expected to see error but got %v for %q", err, rr.Command())
}
t.Logf("Attempting restart after unsuccessful downgrade")
args = append([]string{"start", "-p", profile, "--memory=2200", fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion), "--alsologtostderr", "-v=1"}, StartArgs()...)
rr, err = Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
t.Errorf("start after failed upgrade: %s: %v", rr.Command(), err)
}
}
2020-07-17 00:34:46 +00:00
// TestMissingUpgrade tests a Docker upgrade where the underlying container is missing
func TestMissingUpgrade(t *testing.T) {
if !DockerDriver() {
t.Skipf("This test is only for Docker")
}
MaybeParallel(t)
profile := UniqueProfileName("missing-upgrade")
ctx, cancel := context.WithTimeout(context.Background(), Minutes(55))
defer CleanupWithLogs(t, profile, cancel)
legacyVersion := "v1.9.1"
tf, err := installRelease(legacyVersion)
2020-07-17 00:34:46 +00:00
if err != nil {
t.Fatalf("%s release installation failed: %v", legacyVersion, err)
2020-07-17 00:34:46 +00:00
}
defer os.Remove(tf.Name())
args := append([]string{"start", "-p", profile, "--memory=2200"}, StartArgs()...)
rr := &RunResult{}
r := func() error {
rr, err = Run(t, exec.CommandContext(ctx, tf.Name(), args...))
return err
}
// Retry up to two times, to allow flakiness for the previous release
if err := retry.Expo(r, 1*time.Second, Minutes(30), 2); err != nil {
t.Fatalf("release start failed: %v", err)
}
rr, err = Run(t, exec.CommandContext(ctx, "docker", "stop", profile))
if err != nil {
t.Fatalf("%s failed: %v", rr.Command(), err)
}
rr, err = Run(t, exec.CommandContext(ctx, "docker", "rm", profile))
if err != nil {
t.Fatalf("%s failed: %v", rr.Command(), err)
}
args = append([]string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=1"}, StartArgs()...)
rr, err = Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
t.Errorf("failed missing container upgrade from %s. args: %s : %v", legacyVersion, rr.Command(), err)
2020-07-17 00:34:46 +00:00
}
}