get image version from kubeadm
parent
56e816767a
commit
7d0ccc24ec
|
@ -18,26 +18,22 @@ limitations under the License.
|
|||
package images
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
|
||||
"k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// builds a docker v2 repository API call in the format https://registry.k8s.io/v2/coredns/coredns/tags/list
|
||||
tagURLTemplate = "https://%s/v2/%s/tags/list"
|
||||
)
|
||||
|
||||
// Pause returns the image name to pull for a given Kubernetes version
|
||||
func Pause(v semver.Version, mirror string) string {
|
||||
// Note: changing this logic requires bumping the preload version
|
||||
|
@ -45,7 +41,7 @@ func Pause(v semver.Version, mirror string) string {
|
|||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants_unix.go
|
||||
imageName := "pause"
|
||||
pv := imageVersion(v, mirror, imageName, "3.6")
|
||||
pv := imageVersion(v, imageName, "3.9")
|
||||
|
||||
return fmt.Sprintf("%s:%s", path.Join(kubernetesRepo(mirror), imageName), pv)
|
||||
}
|
||||
|
@ -70,38 +66,35 @@ func componentImage(name string, v semver.Version, mirror string) string {
|
|||
return fmt.Sprintf("%s:v%s", path.Join(kubernetesRepo(mirror), name), v)
|
||||
}
|
||||
|
||||
// fixes 13136 by getting the latest image version from the registry.k8s.io repository instead of hardcoded
|
||||
func findLatestTagFromRepository(url string, lastKnownGood string) string {
|
||||
client := &http.Client{}
|
||||
errorMsg := fmt.Sprintf("Failed to get latest image version for %s, reverting to version %s.", url, lastKnownGood)
|
||||
|
||||
resp, err := client.Get(url)
|
||||
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
klog.Warningf("%s Error %v", errorMsg, err)
|
||||
func tagFromKubeadm(v, name, lastKnownGood string) string {
|
||||
if runtime.GOOS != "linux" {
|
||||
klog.Warningf("can only get tag from kubeadm on Linux")
|
||||
return lastKnownGood
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
kubeadm, err := download.Binary("kubeadm", v, "linux", runtime.GOARCH, "")
|
||||
if err != nil {
|
||||
klog.Warningf("%s Error %v", errorMsg, err)
|
||||
klog.Warningf("failed to download kubeadm binary: %v", err)
|
||||
return lastKnownGood
|
||||
}
|
||||
|
||||
type TagsResponse struct {
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
tags := TagsResponse{}
|
||||
err = json.Unmarshal(body, &tags)
|
||||
if err != nil || len(tags.Tags) < 1 {
|
||||
klog.Warningf("%s Error %v", errorMsg, err)
|
||||
b, err := exec.Command(kubeadm, "config", "images", "list").Output()
|
||||
if err != nil {
|
||||
klog.Warningf("failed getting kubeadm image list: %v", err)
|
||||
return lastKnownGood
|
||||
}
|
||||
lastTagNum := len(tags.Tags) - 1
|
||||
return tags.Tags[lastTagNum]
|
||||
lines := strings.Split(string(b), "\n")
|
||||
for _, line := range lines {
|
||||
if !strings.Contains(line, name) {
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) != 2 {
|
||||
klog.Warningf("unexpected image format: %s", line)
|
||||
return lastKnownGood
|
||||
}
|
||||
return parts[1]
|
||||
}
|
||||
klog.Warningf("failed to find %q image in kubeadm image list", name)
|
||||
return lastKnownGood
|
||||
}
|
||||
|
||||
// coreDNS returns the images used for CoreDNS
|
||||
|
@ -114,7 +107,7 @@ func coreDNS(v semver.Version, mirror string) string {
|
|||
if semver.MustParseRange("<1.21.0-alpha.1")(v) {
|
||||
imageName = "coredns"
|
||||
}
|
||||
cv := imageVersion(v, mirror, imageName, "v1.8.6")
|
||||
cv := imageVersion(v, imageName, "v1.10.1")
|
||||
|
||||
if mirror == constants.AliyunMirror {
|
||||
imageName = "coredns"
|
||||
|
@ -129,17 +122,17 @@ func etcd(v semver.Version, mirror string) string {
|
|||
// Should match `DefaultEtcdVersion` in:
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
|
||||
imageName := "etcd"
|
||||
ev := imageVersion(v, mirror, imageName, "3.5.0-0")
|
||||
ev := imageVersion(v, imageName, "3.5.7-0")
|
||||
|
||||
return fmt.Sprintf("%s:%s", path.Join(kubernetesRepo(mirror), imageName), ev)
|
||||
}
|
||||
|
||||
func imageVersion(v semver.Version, mirror, imageName, defaultVersion string) string {
|
||||
func imageVersion(v semver.Version, imageName, defaultVersion string) string {
|
||||
versionString := fmt.Sprintf("v%s", v.String())
|
||||
if ver, ok := constants.KubeadmImages[versionString][imageName]; ok {
|
||||
return ver
|
||||
}
|
||||
return findLatestTagFromRepository(fmt.Sprintf(tagURLTemplate, kubernetesRepo(mirror), imageName), defaultVersion)
|
||||
return tagFromKubeadm(versionString, imageName, defaultVersion)
|
||||
}
|
||||
|
||||
// auxiliary returns images that are helpful for running minikube
|
||||
|
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package images
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -93,40 +91,6 @@ registry.k8s.io/coredns/coredns:v1.8.4
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetLatestTag(t *testing.T) {
|
||||
serverResp := "{tags: [\"1.8.7\"]}"
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write([]byte(serverResp))
|
||||
if err != nil {
|
||||
t.Errorf("failed to write https response")
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
var testCases = []struct {
|
||||
name string
|
||||
url string
|
||||
lastKnownGood string
|
||||
wsResponse string
|
||||
expect string
|
||||
}{
|
||||
{name: "VersionGetSuccess", url: server.URL, lastKnownGood: "v1.8.6", wsResponse: `{"name": "coredns", "tags": ["v1.8.9"]}`, expect: "v1.8.9"},
|
||||
{name: "VersionGetFail", url: server.URL, lastKnownGood: "v1.8.6", wsResponse: `{"name": "nah", "nope": ["v1.8.9"]}`, expect: "v1.8.6"},
|
||||
{name: "VersionGetFailNone", url: server.URL, lastKnownGood: "v1.8.6", wsResponse: ``, expect: "v1.8.6"},
|
||||
{name: "VersionGetSuccessMultiple", url: server.URL, lastKnownGood: "v1.8.6", wsResponse: `{"name": "coredns", "tags": ["1.8.7","v1.8.9"]}`, expect: "v1.8.9"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
serverResp = tc.wsResponse
|
||||
resp := findLatestTagFromRepository(tc.url, tc.lastKnownGood)
|
||||
if diff := cmp.Diff(tc.expect, resp); diff != "" {
|
||||
t.Errorf("Incorrect response version (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEssentialsAliyunMirror(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
version string
|
||||
|
|
Loading…
Reference in New Issue