kubeadm: modify SetKubernetesVersion

Without this patch SetKubernetesVersion does not set
a version in all locations where it's called, because
the passed config to it always has a default version
stable-1.

This always triggers the != "" check and the function
returns without setting a version.

Validate against DefaultKubernetesVersion and "" instead.

This fixes all cases where fetching a version from the internet
is not needed at all - e.g. "kubeadm token create".

Also make SetKubernetesVersion default to version.Get().String()
and add unit tests for the function.
pull/58/head
Lubomir I. Ivanov 2018-10-11 02:53:13 +03:00
parent a5b489a3a3
commit fa9940c71c
10 changed files with 84 additions and 43 deletions

View File

@ -391,10 +391,7 @@ func RunConfigView(out io.Writer, client clientset.Interface) error {
func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiv1beta1.InitConfiguration) error {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := phaseutil.SetKubernetesVersion(client, defaultcfg)
if err != nil {
return err
}
phaseutil.SetKubernetesVersion(defaultcfg)
// Default both statically and dynamically, convert to internal API type, and validate everything
// First argument is unset here as we shouldn't load a config file from disk

View File

@ -41,7 +41,6 @@ go_library(
"//cmd/kubeadm/app/phases/markmaster:go_default_library",
"//cmd/kubeadm/app/phases/patchnode:go_default_library",
"//cmd/kubeadm/app/phases/selfhosting:go_default_library",
"//cmd/kubeadm/app/phases/upgrade:go_default_library",
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
@ -49,6 +48,7 @@ go_library(
"//cmd/kubeadm/app/util/config:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//pkg/version:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library",
@ -70,16 +70,19 @@ go_test(
"etcd_test.go",
"kubeconfig_test.go",
"kubelet_test.go",
"util_test.go",
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
"//cmd/kubeadm/test:go_default_library",
"//cmd/kubeadm/test/cmd:go_default_library",
"//cmd/kubeadm/test/kubeconfig:go_default_library",
"//pkg/util/node:go_default_library",
"//pkg/version:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
],

View File

@ -304,10 +304,7 @@ func addGenericFlags(flagSet *pflag.FlagSet, cfgPath *string, skipTokenPrint *bo
func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration, skipTokenPrint bool) error {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := SetKubernetesVersion(client, cfg)
if err != nil {
return err
}
SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)

View File

@ -211,8 +211,7 @@ func NewCmdKubeletConfigUpload() *cobra.Command {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := SetKubernetesVersion(nil, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
@ -250,8 +249,7 @@ func NewCmdKubeletAnnotateCRI() *cobra.Command {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := SetKubernetesVersion(nil, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
@ -322,8 +320,7 @@ func NewCmdKubeletConfigWriteToDisk() *cobra.Command {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := SetKubernetesVersion(nil, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)

View File

@ -73,8 +73,7 @@ func NewCmdMarkMaster() *cobra.Command {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err = SetKubernetesVersion(client, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)

View File

@ -102,8 +102,7 @@ func getSelfhostingSubCommand() *cobra.Command {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err = SetKubernetesVersion(client, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)

View File

@ -70,8 +70,7 @@ func NewCmdUploadConfig() *cobra.Command {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err = SetKubernetesVersion(client, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
kubeadmutil.CheckErr(err)

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,17 +17,14 @@ limitations under the License.
package phases
import (
"os"
"github.com/spf13/cobra"
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/pkg/version"
)
// runCmdPhase creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
@ -51,8 +48,7 @@ func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration)
} else {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := SetKubernetesVersion(nil, cfg)
kubeadmutil.CheckErr(err)
SetKubernetesVersion(cfg)
}
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
@ -65,17 +61,12 @@ func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration)
}
}
// SetKubernetesVersion gets current Kubeadm version and sets it as Kubernetes version of master configuration if not set.
func SetKubernetesVersion(client clientset.Interface, cfg *kubeadmapiv1beta1.InitConfiguration) error {
if cfg.KubernetesVersion != "" {
return nil
}
// SetKubernetesVersion gets the current Kubeadm version and sets it as KubeadmVersion in the config,
// unless it's already set to a value different from the default.
func SetKubernetesVersion(cfg *kubeadmapiv1beta1.InitConfiguration) {
kubeadmVer, _, err := upgrade.NewKubeVersionGetter(client, os.Stdout).KubeadmVersion()
if err != nil {
return err
if cfg.KubernetesVersion != kubeadmapiv1beta1.DefaultKubernetesVersion && cfg.KubernetesVersion != "" {
return
}
cfg.KubernetesVersion = kubeadmVer
return nil
cfg.KubernetesVersion = version.Get().String()
}

View File

@ -0,0 +1,61 @@
/*
Copyright 2018 The Kubernetes Authors.
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 phases
import (
"testing"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/pkg/version"
)
func TestSetKubernetesVersion(t *testing.T) {
ver := version.Get().String()
tests := []struct {
name string
input string
output string
}{
{
name: "empty version is processed",
input: "",
output: ver,
},
{
name: "default version is processed",
input: kubeadmapiv1beta1.DefaultKubernetesVersion,
output: ver,
},
{
name: "any other version is skipped",
input: "v1.12.0",
output: "v1.12.0",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cfg := &kubeadmapiv1beta1.InitConfiguration{ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{KubernetesVersion: test.input}}
SetKubernetesVersion(cfg)
if cfg.KubernetesVersion != test.output {
t.Fatalf("expected %q, got %q", test.output, cfg.KubernetesVersion)
}
})
}
}

View File

@ -211,10 +211,8 @@ func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration, printJoinCommand bool, kubeConfigFile string) error {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
err := phaseutil.SetKubernetesVersion(client, cfg)
if err != nil {
return err
}
phaseutil.SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
glog.V(1).Infoln("[token] loading configurations")
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)