From d953bbf1712b86b3e666452dd17b1070c2c8eb55 Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Wed, 29 Oct 2025 23:27:18 +0800 Subject: [PATCH] refactor TestDownloadOnly --- cmd/minikube/cmd/start_flags.go | 8 +++ pkg/minikube/download/preload.go | 13 ++++ test/integration/aaa_download_only_test.go | 74 ++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/cmd/minikube/cmd/start_flags.go b/cmd/minikube/cmd/start_flags.go index c7627f0468da..0c82c4252e6b 100644 --- a/cmd/minikube/cmd/start_flags.go +++ b/cmd/minikube/cmd/start_flags.go @@ -119,6 +119,7 @@ const ( ha = "ha" nodes = "nodes" preload = "preload" + preloadURL = "preload-url" deleteOnFailure = "delete-on-failure" forceSystemd = "force-systemd" kicBaseImage = "base-image" @@ -196,6 +197,13 @@ func initMinikubeFlags() { startCmd.Flags().Bool(ha, false, "Create Highly Available Multi-Control Plane Cluster with a minimum of three control-plane nodes that will also be marked for work.") startCmd.Flags().IntP(nodes, "n", 1, "The total number of nodes to spin up. Defaults to 1.") startCmd.Flags().Bool(preload, true, "If set, download tarball of preloaded images if available to improve start time. Defaults to true.") + startCmd.Flags().String(preloadURL, "", "override preload download URL (testing only)") + if err := viper.BindPFlag("preload-url", startCmd.Flags().Lookup(preloadURL)); err != nil { + klog.Fatalf("Failed to bind flag: %v", err) + } + if err := startCmd.Flags().MarkHidden("preload-url"); err != nil { + klog.Warningf("Failed to hide %s flag: %v\n", "preload-url", err) + } startCmd.Flags().Bool(noKubernetes, false, "If set, minikube VM/container will start without starting or configuring Kubernetes. (only works on new clusters)") startCmd.Flags().Bool(deleteOnFailure, false, "If set, delete the current cluster if start fails and try again. Defaults to false.") startCmd.Flags().Bool(forceSystemd, false, "If set, force the container runtime to use systemd as cgroup manager. Defaults to false.") diff --git a/pkg/minikube/download/preload.go b/pkg/minikube/download/preload.go index 3f8f7abdadd3..2b4f77ae53bb 100644 --- a/pkg/minikube/download/preload.go +++ b/pkg/minikube/download/preload.go @@ -104,6 +104,11 @@ func remoteTarballURLGitHub(k8sVersion, containerRuntime string) string { } func remoteTarballURL(k8sVersion, containerRuntime string, source preloadSource) string { + overrideURL := viper.GetString("preload-url") + if overrideURL != "" { + klog.V(2).Infof("Using override preload URL: %s", overrideURL) + return overrideURL + } switch source { case preloadSourceGitHub: return remoteTarballURLGitHub(k8sVersion, containerRuntime) @@ -246,7 +251,15 @@ func Preload(k8sVersion, containerRuntime, driverName string) error { if ok && state.source != preloadSourceNone { source = state.source } + url := remoteTarballURL(k8sVersion, containerRuntime, source) + // override URL if flag is set + customURL := viper.GetString("preload-url") + if customURL != "" { + klog.Infof("Using custom preload tarball URL: %s", customURL) + url = customURL + } + var checksum []byte var chksErr error checksum, chksErr = getChecksum(source, k8sVersion, containerRuntime) diff --git a/test/integration/aaa_download_only_test.go b/test/integration/aaa_download_only_test.go index 666826016767..1c96f37bed78 100644 --- a/test/integration/aaa_download_only_test.go +++ b/test/integration/aaa_download_only_test.go @@ -34,6 +34,8 @@ import ( "strings" "testing" + "github.com/spf13/viper" + "k8s.io/klog/v2" "k8s.io/minikube/pkg/minikube/bootstrapper/images" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/download" @@ -145,6 +147,78 @@ func TestDownloadOnly(t *testing.T) { // nolint:gocyclo } }) + t.Run("preload-failed", func(t *testing.T) { + args := []string{"start", "-p", profile, "--download-only", "--alsologtostderr"} + rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) + if err != nil { + t.Logf("start with invalid preload-url failed as expected %q : %v", rr.Command(), err) + } else { + t.Errorf("start with invalid preload-url expected to fail, but succeeded: %q", rr.Command()) + } + viper.Set("preload-url", "http://invalid-url/preload.tar.gz") + klog.Infof("preload-url: %s", viper.GetString("preload-url")) + + // checking binaries downloaded (kubelet,kubeadm) + for _, bin := range constants.KubernetesReleaseBinaries { + fp := filepath.Join(localpath.MiniPath(), "cache", "linux", runtime.GOARCH, v, bin) + _, err := os.Stat(fp) + if err != nil { + t.Errorf("expected the file for binary exist at %q but got error %v", fp, err) + } + } + + imgs, err := images.Kubeadm("", v) + if err != nil { + t.Errorf("failed to get kubeadm images for %v: %+v", v, err) + } + + for _, img := range imgs { + pathToImage := []string{localpath.MiniPath(), "cache", "images", runtime.GOARCH} + img = strings.Replace(img, ":", "_", 1) // for example kube-scheduler:v1.15.2 --> kube-scheduler_v1.15.2 + imagePath := strings.Split(img, "/") // changes "gcr.io/k8s-minikube/storage-provisioner_v5" into ["gcr.io", "k8s-minikube", "storage-provisioner_v5"] to match cache folder structure + pathToImage = append(pathToImage, imagePath...) + fp := filepath.Join(pathToImage...) + _, err := os.Stat(fp) + if err != nil { + t.Errorf("expected image file exist at %q but got error: %v", fp, err) + } + } + }) + + t.Run("preload-false", func(t *testing.T) { + args := []string{"start", "-p", profile, "--alsologtostderr", "--preload=false"} + rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) + if err != nil { + t.Errorf("start with preload=false failed %q : %v", rr.Command(), err) + } + + // checking binaries downloaded (kubelet,kubeadm) + for _, bin := range constants.KubernetesReleaseBinaries { + fp := filepath.Join(localpath.MiniPath(), "cache", "linux", runtime.GOARCH, v, bin) + _, err := os.Stat(fp) + if err != nil { + t.Errorf("expected the file for binary exist at %q but got error %v", fp, err) + } + } + + imgs, err := images.Kubeadm("", v) + if err != nil { + t.Errorf("failed to get kubeadm images for %v: %+v", v, err) + } + + for _, img := range imgs { + pathToImage := []string{localpath.MiniPath(), "cache", "images", runtime.GOARCH} + img = strings.Replace(img, ":", "_", 1) // for example kube-scheduler:v1.15.2 --> kube-scheduler_v1.15.2 + imagePath := strings.Split(img, "/") // changes "gcr.io/k8s-minikube/storage-provisioner_v5" into ["gcr.io", "k8s-minikube", "storage-provisioner_v5"] to match cache folder structure + pathToImage = append(pathToImage, imagePath...) + fp := filepath.Join(pathToImage...) + _, err := os.Stat(fp) + if err != nil { + t.Errorf("expected image file exist at %q but got error: %v", fp, err) + } + } + }) + t.Run("binaries", func(t *testing.T) { if preloadExists { t.Skip("Preload exists, binaries are present within.")