Merge pull request #14006 from ckannon/fixes/13136
Get latest valid tag for each image during cacheingpull/14154/head
commit
958819cba0
|
|
@ -18,9 +18,14 @@ limitations under the License.
|
|||
package images
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
|
|
@ -28,6 +33,11 @@ import (
|
|||
"k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// builds a docker v2 repository API call in the format https://k8s.gcr.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
|
||||
|
|
@ -35,10 +45,13 @@ 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
|
||||
pv := "3.6"
|
||||
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)
|
||||
imageName := "pause"
|
||||
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)
|
||||
|
||||
if pVersion, ok := constants.KubeadmImages[majorMinorVersion][imageName]; ok {
|
||||
pv = pVersion
|
||||
} else {
|
||||
pv = findLatestTagFromRepository(fmt.Sprintf(tagURLTemplate, kubernetesRepo(mirror), imageName), pv)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s:%s", path.Join(kubernetesRepo(mirror), imageName), pv)
|
||||
|
|
@ -64,24 +77,60 @@ 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 k8s.gcr.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)
|
||||
return lastKnownGood
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
klog.Warningf("%s Error %v", errorMsg, 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)
|
||||
return lastKnownGood
|
||||
}
|
||||
lastTagNum := len(tags.Tags) - 1
|
||||
return tags.Tags[lastTagNum]
|
||||
}
|
||||
|
||||
// coreDNS returns the images used for CoreDNS
|
||||
func coreDNS(v semver.Version, mirror string) string {
|
||||
// Note: changing this logic requires bumping the preload version
|
||||
// Should match `CoreDNSImageName` and `CoreDNSVersion` in
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
|
||||
|
||||
cv := "1.8.4"
|
||||
in := "coredns/coredns"
|
||||
imageName := "coredns/coredns"
|
||||
cv := "v1.8.6"
|
||||
if semver.MustParseRange("<1.21.0-alpha.1")(v) {
|
||||
in = "coredns"
|
||||
imageName = "coredns"
|
||||
}
|
||||
|
||||
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)
|
||||
if cVersion, ok := constants.KubeadmImages[majorMinorVersion][in]; ok {
|
||||
if cVersion, ok := constants.KubeadmImages[majorMinorVersion][imageName]; ok {
|
||||
cv = cVersion
|
||||
} else {
|
||||
cv = findLatestTagFromRepository(fmt.Sprintf(tagURLTemplate, kubernetesRepo(mirror), imageName), cv)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s:%s", path.Join(kubernetesRepo(mirror), in), cv)
|
||||
return fmt.Sprintf("%s:%s", path.Join(kubernetesRepo(mirror), imageName), cv)
|
||||
}
|
||||
|
||||
// etcd returns the image used for etcd
|
||||
|
|
@ -90,10 +139,12 @@ 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
|
||||
ev := "3.5.0-0"
|
||||
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)
|
||||
imageName := "etcd"
|
||||
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)
|
||||
if eVersion, ok := constants.KubeadmImages[majorMinorVersion][imageName]; ok {
|
||||
ev = eVersion
|
||||
} else {
|
||||
ev = findLatestTagFromRepository(fmt.Sprintf(tagURLTemplate, kubernetesRepo(mirror), imageName), ev)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s:%s", path.Join(kubernetesRepo(mirror), imageName), ev)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package images
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -91,6 +93,40 @@ k8s.gcr.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 TestAuxiliary(t *testing.T) {
|
||||
want := []string{
|
||||
"gcr.io/k8s-minikube/storage-provisioner:" + version.GetStorageProvisionerVersion(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue