Skip to content

Commit

Permalink
Gets latest valid tag for each image
Browse files Browse the repository at this point in the history
  • Loading branch information
ckannon committed Apr 21, 2022
1 parent a799c83 commit c0a82b4
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 3 deletions.
56 changes: 53 additions & 3 deletions pkg/minikube/bootstrapper/images/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ limitations under the License.
package images

import (
"encoding/json"
"fmt"
"io"
"k8s.io/klog/v2"
"net/http"
"path"

"k8s.io/minikube/pkg/minikube/constants"
Expand All @@ -28,15 +32,21 @@ import (
"k8s.io/minikube/pkg/version"
)

const (
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
// Should match `PauseVersion` in:
// 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"
pv = getLatestTag(fmt.Sprintf(tagUrlTemplate, kubernetesRepo(mirror), imageName), pv)
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)

if pVersion, ok := constants.KubeadmImages[majorMinorVersion][imageName]; ok {
pv = pVersion
}
Expand Down Expand Up @@ -64,14 +74,53 @@ func componentImage(name string, v semver.Version, mirror string) string {
return fmt.Sprintf("%s:v%s", path.Join(kubernetesRepo(mirror), name), v)
}

func getLatestTag(url string, lastKnownGood string) string {
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)

if err != nil {
klog.Infof("Failed to get latest image version for %s, reverting to version %s\n", url, lastKnownGood)
return lastKnownGood
}

resp, err := client.Do(req)

if err != nil || resp.StatusCode != http.StatusOK {
klog.Infof("Failed to get latest image version for %s, reverting to version %s\n", url, lastKnownGood)
return lastKnownGood
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
klog.Infof("Failed to read latest image version for %s, reverting to version %s\n", url, lastKnownGood)
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.Infof("Failed to read latest image version for %s, reverting to version %s\n", url, lastKnownGood)
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"
cv := "v1.8.6"
cv = getLatestTag(fmt.Sprintf(tagUrlTemplate, kubernetesRepo(mirror), in), cv)
if semver.MustParseRange("<1.21.0-alpha.1")(v) {
in = "coredns"
}
Expand All @@ -90,8 +139,9 @@ 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"
ev = getLatestTag(fmt.Sprintf(tagUrlTemplate, kubernetesRepo(mirror), ev), ev)
majorMinorVersion := fmt.Sprintf("v%d.%d", v.Major, v.Minor)
if eVersion, ok := constants.KubeadmImages[majorMinorVersion][imageName]; ok {
ev = eVersion
}
Expand Down
33 changes: 33 additions & 0 deletions pkg/minikube/bootstrapper/images/images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package images

import (
"net/http"
"net/http/httptest"
"strings"
"testing"

Expand Down Expand Up @@ -91,6 +93,37 @@ 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)
w.Write([]byte(serverResp))
}))
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 := getLatestTag(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(),
Expand Down

0 comments on commit c0a82b4

Please sign in to comment.