-
Notifications
You must be signed in to change notification settings - Fork 5.1k
fixes get ETCD version from kubernetes constants #11290 #12084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
5f46b98
8f04834
efbfbc1
837c73d
ddfcf46
e744f3e
6a9d08e
ab496e6
7e7a97e
2d7e884
991d9d4
fce35c9
d0928b1
7dd0eb0
c80793c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
/* | ||
Copyright 2021 The Kubernetes Authors All rights reserved. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
"text/template" | ||
"time" | ||
|
||
"golang.org/x/mod/semver" | ||
"k8s.io/klog/v2" | ||
"k8s.io/minikube/hack/update" | ||
"k8s.io/minikube/pkg/minikube/constants" | ||
) | ||
|
||
const ( | ||
// default context timeout | ||
cxTimeout = 300 * time.Second | ||
kubeadmReleaseURL = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubeadm" | ||
kubeadmBinaryName = "kubeadm-linux-amd64-%s" | ||
minikubeConstantsFilePath = "pkg/minikube/constants/constants_kubeadm_images.go" | ||
kubeadmImagesTemplate = ` | ||
{{- range $version, $element := .}} | ||
"{{$version}}": { | ||
{{- range $image, $tag := $element}} | ||
"{{$image}}": "{{$tag}}", | ||
{{- end}} | ||
},{{- end}}` | ||
) | ||
|
||
// Data contains kubeadm Images map | ||
type Data struct { | ||
ImageMap string `json:"ImageMap"` | ||
} | ||
|
||
func main() { | ||
|
||
inputVersion := flag.Lookup("kubernetes-version").Value.String() | ||
|
||
imageVersions := make([]string, 0) | ||
|
||
// set a context with defined timeout | ||
ctx, cancel := context.WithTimeout(context.Background(), cxTimeout) | ||
defer cancel() | ||
|
||
if inputVersion == "latest" { | ||
stableImageVersion, latestImageVersion, err := getK8sVersions(ctx, "kubernetes", "kubernetes") | ||
if err != nil { | ||
klog.Fatal(err) | ||
} | ||
imageVersions = append(imageVersions, stableImageVersion, latestImageVersion) | ||
} else if semver.IsValid(inputVersion) { | ||
imageVersions = append(imageVersions, inputVersion) | ||
} else { | ||
klog.Fatal(errors.New("invalid version")) | ||
} | ||
|
||
for _, imageVersion := range imageVersions { | ||
imageMapString, err := getKubeadmImagesMapString(imageVersion) | ||
if err != nil { | ||
klog.Fatalln(err) | ||
} | ||
|
||
var data Data | ||
schema := map[string]update.Item{ | ||
minikubeConstantsFilePath: { | ||
Replace: map[string]string{}, | ||
}, | ||
} | ||
|
||
majorMinorVersion := semver.MajorMinor(imageVersion) | ||
|
||
if _, ok := constants.KubeadmImages[majorMinorVersion]; !ok { | ||
data = Data{ImageMap: imageMapString} | ||
schema[minikubeConstantsFilePath].Replace[`KubeadmImages = .*`] = | ||
`KubeadmImages = map[string]map[string]string{ {{.ImageMap}}` | ||
} else { | ||
data = Data{ImageMap: strings.TrimLeft(imageMapString, "\n")} | ||
versionIdentifier := fmt.Sprintf(`"%s": {[^}]+},`, majorMinorVersion) | ||
schema[minikubeConstantsFilePath].Replace[versionIdentifier] = "{{.ImageMap}}" | ||
} | ||
|
||
update.Apply(ctx, schema, data, "", "", -1) | ||
} | ||
} | ||
|
||
func getKubeadmImagesMapString(version string) (string, error) { | ||
url := fmt.Sprintf(kubeadmReleaseURL, version) | ||
fileName := fmt.Sprintf(kubeadmBinaryName, version) | ||
if err := downloadFile(url, fileName); err != nil { | ||
klog.Errorf("failed to download kubeadm binary %s", err.Error()) | ||
return "", err | ||
} | ||
|
||
kubeadmCommand := fmt.Sprintf("./%s", fileName) | ||
args := []string{"config", "images", "list"} | ||
imageListString, err := executeCommand(kubeadmCommand, args...) | ||
if err != nil { | ||
klog.Errorf("failed to execute kubeadm command %s", kubeadmCommand) | ||
return "", err | ||
} | ||
|
||
if err := os.Remove(fileName); err != nil { | ||
klog.Errorf("failed to remove binary %s", fileName) | ||
} | ||
|
||
return formatKubeadmImageList(version, imageListString) | ||
} | ||
|
||
func formatKubeadmImageList(version, data string) (string, error) { | ||
templateData := make(map[string]map[string]string) | ||
majorMinorVersion := semver.MajorMinor(version) | ||
templateData[majorMinorVersion] = make(map[string]string) | ||
lines := strings.Split(data, "\n") | ||
for _, line := range lines { | ||
imageTag := strings.Split(line, ":") | ||
if len(imageTag) == 2 { | ||
templateData[majorMinorVersion][imageTag[0]] = imageTag[1] | ||
} | ||
} | ||
|
||
imageTemplate := template.New("kubeadmImage") | ||
t, err := imageTemplate.Parse(kubeadmImagesTemplate) | ||
if err != nil { | ||
klog.Errorf("failed to create kubeadm image map template %s", err.Error()) | ||
return "", err | ||
} | ||
|
||
var bytesBuffer bytes.Buffer | ||
if err := t.Execute(&bytesBuffer, &templateData); err != nil { | ||
return "", err | ||
} | ||
|
||
return bytesBuffer.String(), nil | ||
} | ||
|
||
func downloadFile(url, fileName string) error { | ||
file, err := os.Create(fileName) | ||
if err != nil { | ||
return err | ||
} | ||
defer file.Close() | ||
|
||
response, err := http.Get(url) | ||
if err != nil { | ||
return err | ||
} | ||
defer response.Body.Close() | ||
|
||
if response.StatusCode != http.StatusOK { | ||
return fmt.Errorf("non success status code, while downloading file: %s from: %s", fileName, url) | ||
} | ||
|
||
if _, err := io.Copy(file, response.Body); err != nil { | ||
return err | ||
} | ||
|
||
return os.Chmod(fileName, os.ModePerm) | ||
} | ||
|
||
func executeCommand(command string, args ...string) (string, error) { | ||
output, err := exec.Command(command, args...).Output() | ||
if err != nil { | ||
return "", err | ||
} | ||
return string(output), nil | ||
} | ||
|
||
// getK8sVersion returns Kubernetes versions. | ||
func getK8sVersions(ctx context.Context, owner, repo string) (stable, latest string, err error) { | ||
// get Kubernetes versions from GitHub Releases | ||
stable, latest, err = update.GHReleases(ctx, owner, repo) | ||
if err != nil { | ||
return "", "", err | ||
} | ||
|
||
if !semver.IsValid(stable) || !semver.IsValid(latest) { | ||
return "", "", fmt.Errorf("invalid release obtained stable : %s, latest : %s", stable, latest) | ||
} | ||
|
||
return stable, latest, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,17 +46,17 @@ func TestKubeadmImages(t *testing.T) { | |
"docker.io/kubernetesui/dashboard:v2.3.1", | ||
"docker.io/kubernetesui/metrics-scraper:v1.0.7", | ||
}}, | ||
{"v1.16.1", "mirror.k8s.io", false, []string{ | ||
"mirror.k8s.io/kube-proxy:v1.16.1", | ||
"mirror.k8s.io/kube-scheduler:v1.16.1", | ||
"mirror.k8s.io/kube-controller-manager:v1.16.1", | ||
"mirror.k8s.io/kube-apiserver:v1.16.1", | ||
"mirror.k8s.io/coredns:1.6.2", | ||
"mirror.k8s.io/etcd:3.3.15-0", | ||
"mirror.k8s.io/pause:3.1", | ||
"mirror.k8s.io/k8s-minikube/storage-provisioner:" + version.GetStorageProvisionerVersion(), | ||
"mirror.k8s.io/kubernetesui/dashboard:v2.3.1", | ||
"mirror.k8s.io/kubernetesui/metrics-scraper:v1.0.7", | ||
{"v1.16.1", "k8s.gcr.io", false, []string{ | ||
|
||
"k8s.gcr.io/kube-proxy:v1.16.1", | ||
"k8s.gcr.io/kube-scheduler:v1.16.1", | ||
"k8s.gcr.io/kube-controller-manager:v1.16.1", | ||
"k8s.gcr.io/kube-apiserver:v1.16.1", | ||
"k8s.gcr.io/coredns:1.6.2", | ||
"k8s.gcr.io/etcd:3.3.15-0", | ||
"k8s.gcr.io/pause:3.1", | ||
"k8s.gcr.io/k8s-minikube/storage-provisioner:" + version.GetStorageProvisionerVersion(), | ||
"k8s.gcr.io/kubernetesui/dashboard:v2.3.1", | ||
"k8s.gcr.io/kubernetesui/metrics-scraper:v1.0.7", | ||
}}, | ||
{"v1.15.0", "", false, []string{ | ||
"k8s.gcr.io/kube-proxy:v1.15.0", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems like missing "kubernetesRepo(mirror)" don't we need that for --image-repositories and mirrors and china users?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed it.