Skip to content
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

list all currently supported Kubernetes versions #13775

Merged
merged 5 commits into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cmd/minikube/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ var settings = []Setting{
validations: []setFn{IsValidPath},
},
{
name: "kubernetes-version",
set: SetString,
name: "kubernetes-version",
set: SetString,
validDefaults: supportedKubernetesVersions,
},
{
name: "iso-url",
Expand Down
47 changes: 27 additions & 20 deletions cmd/minikube/cmd/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,31 @@ import (
"fmt"
"strings"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/reason"
)

var defaultsOutput string

var configDefaultsCommand = &cobra.Command{
Use: "defaults PROPERTY_NAME",
Short: "Lists all valid default values for PROPERTY_NAME",
Long: `list displays all valid default settings for PROPERTY_NAME
Acceptable fields: ` + "\n\n" + fieldsWithDefaults(),
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
cmd.SilenceErrors = true
return errors.New("not enough arguments.\nusage: minikube config list PROPERTY_NAME")
}
if len(args) > 1 {
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
cmd.SilenceErrors = true
return fmt.Errorf("too many arguments (%d)\nusage: minikube config list PROPERTY_NAME", len(args))
exit.Message(reason.Usage, "usage: minikube config list PROPERTY_NAME")
}

property := args[0]
defaults, err := getDefaults(property)
if err != nil {
return err
exit.Message(reason.Usage, "error getting defaults: {{.error}}", out.V{"error": err})
}
return printDefaults(defaults)
printDefaults(defaults)
},
}

Expand All @@ -61,19 +60,27 @@ func getDefaults(property string) ([]string, error) {
return setting.validDefaults(), nil
}

func printDefaults(defaults []string) error {
if output == "json" {
func printDefaults(defaults []string) {
switch strings.ToLower(defaultsOutput) {
case "":
for _, d := range defaults {
out.Ln("* %s", d)
}
case "json":
encoding, err := json.Marshal(defaults)
if err != nil {
return errors.Wrap(err, "encoding json")
exit.Error(reason.InternalJSONMarshal, "json encoding failure", err)
}
out.Ln(string(encoding))
return nil
}
for _, d := range defaults {
out.Ln("* %s", d)
case "yaml":
encoding, err := yaml.Marshal(defaults)
if err != nil {
exit.Error(reason.InternalYamlMarshal, "yaml encoding failure", err)
}
out.Ln(string(encoding))
default:
exit.Message(reason.InternalOutputUsage, "error: --output must be 'yaml' or 'json'")
}
return nil
}

func fieldsWithDefaults() string {
Expand All @@ -87,6 +94,6 @@ func fieldsWithDefaults() string {
}

func init() {
configDefaultsCommand.Flags().StringVar(&output, "output", "", "Output format. Accepted values: [json]")
configDefaultsCommand.Flags().StringVarP(&defaultsOutput, "output", "o", "", "Output format. Accepted values: [json, yaml]")
ConfigCmd.AddCommand(configDefaultsCommand)
}
6 changes: 2 additions & 4 deletions cmd/minikube/cmd/config/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,10 @@ func TestPrintDefaults(t *testing.T) {
}
for _, tc := range tcs {
t.Run(tc.description, func(t *testing.T) {
output = tc.format
defaultsOutput = tc.format
f := tests.NewFakeFile()
out.SetOutFile(f)
if err := printDefaults(defaults); err != nil {
t.Fatalf("error printing defaults: %v", err)
}
printDefaults(defaults)
if f.String() != tc.expected {
t.Fatalf("Expected: %v\n Actual: %v\n", tc.expected, f.String())
}
Expand Down
66 changes: 66 additions & 0 deletions cmd/minikube/cmd/config/kubernetes_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright 2022 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 config

import (
"context"
"sort"

"github.com/google/go-github/v43/github"
"golang.org/x/mod/semver"
"k8s.io/minikube/pkg/minikube/constants"
)

// supportedKubernetesVersions returns reverse-sort supported Kubernetes releases from GitHub that are in [constants.OldestKubernetesVersion, constants.NewestKubernetesVersion] range, including prereleases.
// in case it cannot get it from GitHub, in addition to [constants.NewestKubernetesVersion, constants.OldestKubernetesVersion], 'constants.DefaultKubernetesVersion' is also returned if different from 'constants.NewestKubernetesVersion'.
func supportedKubernetesVersions() (releases []string) {
minver := constants.OldestKubernetesVersion
defver := constants.DefaultKubernetesVersion
maxver := constants.NewestKubernetesVersion

ghc := github.NewClient(nil)

opts := &github.ListOptions{PerPage: 100}
for (opts.Page+1)*100 <= 300 {
rls, resp, err := ghc.Repositories.ListReleases(context.Background(), "kubernetes", "kubernetes", opts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prezha one of the use cases of this feature would be in the minikube GUI, when we load the page to create a cluster we can list all supported kubernetes versions, this will make a http call (not very cheap) in the gui.

i suggest this code to only reference the constants and if needed add some sort of automation (in Makefile) to generate this list. instead of making the call each single time.

is that reasonable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@medyagh that's a good use case as well

this func (exposed via CLI) takes ~1.7sec to produce a fresh list of all currently acceptable k8s versions, which indeed is not that cheap

now, the release cadence for minikube is ~monthly, whereas k8s (supporting the last 3 of its minor versions) has it more frequently, and therefore we/user could end up with the outdated static list (especially if a user did not upgrade to the latest minikube version)

i'd suggest keeping this func/cli functionality as-is in this pr, and for the GUI use case, we could ship minikube releases with a "hardcoded" list of all supported k8s versions (known at the time of the release) and also have eg, a "Refresh" link/button nearby to call this func again so that the GUI can regenerate and cache results for later reuse?

what do you think?

Copy link
Member

@spowelljr spowelljr Apr 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the person working on the GUI, on GUI startup we could make a call to this function and cache the result. So by the time the user gets around to starting the cluster with a custom k8s version, the list will already be cached and will be able to validate the users input with no latency. I'm not arguing the solution either way, but stating that I don't believe this will impact the GUI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spowelljr yes, thanks, that sounds like a good/optimal solution to me

@medyagh would you agree then that we keep this func[tionality] as-is in this pr and Steven will call it as needed and also cache results on the gui side?

if err != nil {
v := []string{maxver}
if defver != maxver {
v = append(v, defver)
}
v = append(v, minver)
return v
}
for _, rl := range rls {
ver := rl.GetTagName()
if !semver.IsValid(ver) {
continue
}
// skip out-of-range versions
if (minver != "" && semver.Compare(minver, ver) == 1) || (maxver != "" && semver.Compare(ver, maxver) == 1) {
continue
}
releases = append(releases, ver)
}
if resp.NextPage == 0 {
break
}
opts.Page = resp.NextPage
}
sort.Slice(releases, func(i, j int) bool { return semver.Compare(releases[i], releases[j]) == 1 })
return releases
}
8 changes: 4 additions & 4 deletions cmd/minikube/cmd/config/profile_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,21 @@ import (
"k8s.io/klog/v2"
)

var output string
var profileOutput string
var isLight bool

var profileListCmd = &cobra.Command{
Use: "list",
Short: "Lists all minikube profiles.",
Long: "Lists all valid minikube profiles and detects all possible invalid profiles.",
Run: func(cmd *cobra.Command, args []string) {
switch strings.ToLower(output) {
switch strings.ToLower(profileOutput) {
case "json":
printProfilesJSON()
case "table":
printProfilesTable()
default:
exit.Message(reason.Usage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", output))
exit.Message(reason.Usage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", profileOutput))
}
},
}
Expand Down Expand Up @@ -217,7 +217,7 @@ func profilesOrDefault(profiles []*config.Profile) []*config.Profile {
}

func init() {
profileListCmd.Flags().StringVarP(&output, "output", "o", "table", "The output format. One of 'json', 'table'")
profileListCmd.Flags().StringVarP(&profileOutput, "output", "o", "table", "The output format. One of 'json', 'table'")
profileListCmd.Flags().BoolVarP(&isLight, "light", "l", false, "If true, returns list of profiles faster by skipping validating the status of the cluster.")
ProfileCmd.AddCommand(profileListCmd)
}
4 changes: 2 additions & 2 deletions cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -1585,10 +1585,10 @@ func validateKubernetesVersion(old *config.ClusterConfig) {
exitIfNotForced(reason.KubernetesTooNew, "Kubernetes {{.version}} is not supported by this release of minikube", out.V{"version": nvs})
}
if nvs.GT(newestVersion) {
out.WarningT("Specified Kubernetes version {{.specified}} is newer than the newest supported version: {{.newest}}", out.V{"specified": nvs, "newest": constants.NewestKubernetesVersion})
out.WarningT("Specified Kubernetes version {{.specified}} is newer than the newest supported version: {{.newest}}. Use `minikube config defaults kubernetes-version` for details.", out.V{"specified": nvs, "newest": constants.NewestKubernetesVersion})
}
if nvs.LT(oldestVersion) {
out.WarningT("Specified Kubernetes version {{.specified}} is less than the oldest supported version: {{.oldest}}", out.V{"specified": nvs, "oldest": constants.OldestKubernetesVersion})
out.WarningT("Specified Kubernetes version {{.specified}} is less than the oldest supported version: {{.oldest}}. Use `minikube config defaults kubernetes-version` for details.", out.V{"specified": nvs, "oldest": constants.OldestKubernetesVersion})
if !viper.GetBool(force) {
out.WarningT("You can force an unsupported Kubernetes version via the --force flag")
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var versionCmd = &cobra.Command{
Run: func(command *cobra.Command, args []string) {
minikubeVersion := version.GetVersion()
gitCommitID := version.GetGitCommitID()
data := map[string]string{
data := map[string]interface{}{
"minikubeVersion": minikubeVersion,
"commit": gitCommitID,
}
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ require (
require (
github.com/Xuanwo/go-locale v1.1.0
github.com/docker/go-connections v0.4.0
github.com/google/go-github/v43 v43.0.0
github.com/opencontainers/runc v1.0.2
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
)
Expand Down Expand Up @@ -153,7 +154,7 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.3.0 // indirect
github.com/googleapis/go-type-adapters v1.0.0 // indirect
Expand Down
5 changes: 4 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,11 @@ github.com/google/go-containerregistry v0.6.0/go.mod h1:euCCtNbZ6tKqi1E72vwDj2xZ
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
github.com/google/go-github/v36 v36.0.0/go.mod h1:LFlKC047IOqiglRGNqNb9s/iAPTnnjtlshm+bxp+kwk=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-github/v43 v43.0.0 h1:y+GL7LIsAIF2NZlJ46ZoC/D1W1ivZasT0lnWHMYPZ+U=
github.com/google/go-github/v43 v43.0.0/go.mod h1:ZkTvvmCXBvsfPpTHXnH/d2hP9Y0cTbvN9kr5xqyXOIc=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down