From 75bc3f2b42dce3da505896a12d3154f5bf90eb95 Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Fri, 6 Oct 2023 10:19:02 -0700 Subject: [PATCH 1/2] check existing minor versions to get image tag --- pkg/minikube/bootstrapper/images/images.go | 45 ++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/pkg/minikube/bootstrapper/images/images.go b/pkg/minikube/bootstrapper/images/images.go index 3432df5d7687..d7dc380987a7 100644 --- a/pkg/minikube/bootstrapper/images/images.go +++ b/pkg/minikube/bootstrapper/images/images.go @@ -24,8 +24,6 @@ import ( "runtime" "strings" - "k8s.io/klog/v2" - "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/download" @@ -66,21 +64,19 @@ func componentImage(name string, v semver.Version, mirror string) string { return fmt.Sprintf("%s:v%s", path.Join(kubernetesRepo(mirror), name), v) } -func tagFromKubeadm(v, name, lastKnownGood string) string { +// tagFromKubeadm gets the image tag by running kubeadm image list command on the host machine (Linux only) +func tagFromKubeadm(v, name string) (string, error) { if runtime.GOOS != "linux" { - klog.Warningf("can only get tag from kubeadm on Linux") - return lastKnownGood + return "", fmt.Errorf("can only get tag from kubeadm on Linux") } kubeadm, err := download.Binary("kubeadm", v, "linux", runtime.GOARCH, "") if err != nil { - klog.Warningf("failed to download kubeadm binary: %v", err) - return lastKnownGood + return "", fmt.Errorf("failed to download kubeadm binary: %v", err) } // TODO: Once kubeadm graduates the "-experimental-output" flag to non-experimental should use JSON output here b, err := exec.Command(kubeadm, "config", "images", "list").Output() if err != nil { - klog.Warningf("failed getting kubeadm image list: %v", err) - return lastKnownGood + return "", fmt.Errorf("failed getting kubeadm image list: %v", err) } lines := strings.Split(string(b), "\n") for _, line := range lines { @@ -89,13 +85,29 @@ func tagFromKubeadm(v, name, lastKnownGood string) string { } parts := strings.Split(line, ":") if len(parts) != 2 { - klog.Warningf("unexpected image format: %s", line) - return lastKnownGood + return "", fmt.Errorf("unexpected image format: %s", line) } - return parts[1] + return parts[1], nil } - klog.Warningf("failed to find %q image in kubeadm image list", name) - return lastKnownGood + return "", fmt.Errorf("failed to find %q image in kubeadm image list", name) +} + +// tagFromLastMinor finds the last matching minor version in the kubeadm images map and uses its image version +func tagFromLastMinor(v semver.Version, name, lastKnownGood string) string { + majorMinor := fmt.Sprintf("v%d.%d", v.Major, v.Minor) + var latestMinorVer string + for _, existingVer := range constants.ValidKubernetesVersions { + if !strings.HasPrefix(existingVer, majorMinor) { + continue + } + latestMinorVer = existingVer + break + } + tag, ok := constants.KubeadmImages[latestMinorVer][name] + if !ok { + return lastKnownGood + } + return tag } // coreDNS returns the images used for CoreDNS @@ -133,7 +145,10 @@ func imageVersion(v semver.Version, imageName, defaultVersion string) string { if ver, ok := constants.KubeadmImages[versionString][imageName]; ok { return ver } - return tagFromKubeadm(versionString, imageName, defaultVersion) + if ver, err := tagFromKubeadm(versionString, imageName); err == nil { + return ver + } + return tagFromLastMinor(v, imageName, defaultVersion) } // auxiliary returns images that are helpful for running minikube From 6982d3a32c779c574620c7a0371cd2ecb65edd5c Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Fri, 6 Oct 2023 10:51:58 -0700 Subject: [PATCH 2/2] add test for tagFromLastMinor --- .../bootstrapper/images/images_test.go | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pkg/minikube/bootstrapper/images/images_test.go b/pkg/minikube/bootstrapper/images/images_test.go index ba2d05e7fa70..341244e00498 100644 --- a/pkg/minikube/bootstrapper/images/images_test.go +++ b/pkg/minikube/bootstrapper/images/images_test.go @@ -180,3 +180,28 @@ func TestCNI(t *testing.T) { }) } } + +func TestTagFromLastMinor(t *testing.T) { + tests := []struct { + verString string + imageName string + expectedTag string + }{ + {"1.16.50", "coredns", "1.6.2"}, + {"1.16.50", "etcd", "3.3.15-0"}, + {"1.16.50", "pause", "3.1"}, + {"1.16.50", "fake", "default"}, + } + + for _, tc := range tests { + v, err := semver.Parse(tc.verString) + if err != nil { + t.Errorf("failed to parse version to semver: %v", err) + continue + } + got := tagFromLastMinor(v, tc.imageName, "default") + if tc.expectedTag != got { + t.Errorf("tagFromLastMinor(%s, %s, default) = %s; want = %s", tc.verString, tc.imageName, got, tc.expectedTag) + } + } +}