Skip to content

Commit e7427c6

Browse files
committed
kubeadm: Merge getK8sVersionFromUserInput into enforceRequirements
`getK8sVersionFromUserInput` would attempt to load the config from a user specified YAML file (via the `--config` option of `kubeadm upgrade plan` or `kubeadm upgrade apply`). This is done in order to fetch the `KubernetesVersion` field of the `ClusterConfiguration`. The complete config is then immediately discarded. The actual config that is used during the upgrade process is fetched from within `enforceRequirements`. This, along with the fact that `getK8sVersionFromUserInput` is always called immediately after `enforceRequirements` makes it possible to merge the two. Merging them would help us simplify things and avoid future problems in component config related patches. Signed-off-by: Rostislav M. Georgiev <[email protected]>
1 parent 4cc44fb commit e7427c6

File tree

4 files changed

+26
-136
lines changed

4 files changed

+26
-136
lines changed

cmd/kubeadm/app/cmd/upgrade/apply.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,7 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
7373
DisableFlagsInUseLine: true,
7474
Short: "Upgrade your Kubernetes cluster to the specified version",
7575
RunE: func(cmd *cobra.Command, args []string) error {
76-
userVersion, err := getK8sVersionFromUserInput(flags.applyPlanFlags, args, true)
77-
if err != nil {
78-
return err
79-
}
80-
81-
return runApply(flags, userVersion)
76+
return runApply(flags, args)
8277
},
8378
}
8479

@@ -110,12 +105,12 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
110105
// - Creating the RBAC rules for the bootstrap tokens and the cluster-info ConfigMap
111106
// - Applying new kube-dns and kube-proxy manifests
112107
// - Uploads the newly used configuration to the cluster ConfigMap
113-
func runApply(flags *applyFlags, userVersion string) error {
108+
func runApply(flags *applyFlags, args []string) error {
114109

115110
// Start with the basics, verify that the cluster is healthy and get the configuration from the cluster (using the ConfigMap)
116111
klog.V(1).Infoln("[upgrade/apply] verifying health of cluster")
117112
klog.V(1).Infoln("[upgrade/apply] retrieving configuration from cluster")
118-
client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, flags.dryRun, userVersion)
113+
client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, args, flags.dryRun, true)
119114
if err != nil {
120115
return err
121116
}

cmd/kubeadm/app/cmd/upgrade/common.go

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,37 +46,8 @@ import (
4646
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
4747
)
4848

49-
func getK8sVersionFromUserInput(flags *applyPlanFlags, args []string, versionIsMandatory bool) (string, error) {
50-
var userVersion string
51-
52-
// If the version is specified in config file, pick up that value.
53-
if flags.cfgPath != "" {
54-
// Note that cfg isn't preserved here, it's just an one-off to populate userVersion based on --config
55-
cfg, err := configutil.LoadInitConfigurationFromFile(flags.cfgPath)
56-
if err != nil {
57-
return "", err
58-
}
59-
60-
userVersion = cfg.KubernetesVersion
61-
}
62-
63-
// the version arg is mandatory unless version is specified in the config file
64-
if versionIsMandatory && userVersion == "" {
65-
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
66-
return "", err
67-
}
68-
}
69-
70-
// If option was specified in both args and config file, args will overwrite the config file.
71-
if len(args) == 1 {
72-
userVersion = args[0]
73-
}
74-
75-
return userVersion, nil
76-
}
77-
7849
// enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure
79-
func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion string) (clientset.Interface, upgrade.VersionGetter, *kubeadmapi.InitConfiguration, error) {
50+
func enforceRequirements(flags *applyPlanFlags, args []string, dryRun bool, upgradeApply bool) (clientset.Interface, upgrade.VersionGetter, *kubeadmapi.InitConfiguration, error) {
8051
client, err := getClient(flags.kubeConfigPath, dryRun)
8152
if err != nil {
8253
return nil, nil, nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
@@ -90,10 +61,18 @@ func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion strin
9061
// Fetch the configuration from a file or ConfigMap and validate it
9162
fmt.Println("[upgrade/config] Making sure the configuration is correct:")
9263

64+
var newK8sVersion string
9365
var cfg *kubeadmapi.InitConfiguration
66+
9467
if flags.cfgPath != "" {
9568
klog.Warning("WARNING: Usage of the --config flag for reconfiguring the cluster during upgrade is not recommended!")
9669
cfg, err = configutil.LoadInitConfigurationFromFile(flags.cfgPath)
70+
71+
// Initialize newK8sVersion to the value in the ClusterConfiguration. This is done, so that users who use the --config option
72+
// don't have to specify the Kubernetes version twice if they don't want to upgrade, but just change a setting.
73+
if err != nil {
74+
newK8sVersion = cfg.KubernetesVersion
75+
}
9776
} else {
9877
cfg, err = configutil.FetchInitConfigurationFromCluster(client, os.Stdout, "upgrade/config", false)
9978
}
@@ -131,8 +110,16 @@ func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion strin
131110
return nil, nil, nil, errors.Wrap(err, "[upgrade/health] FATAL")
132111
}
133112

134-
// If a new k8s version should be set, apply the change before printing the config
135-
if len(newK8sVersion) != 0 {
113+
// The version arg is mandatory, during upgrade apply, unless it's specified in the config file
114+
if upgradeApply && newK8sVersion == "" {
115+
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
116+
return nil, nil, nil, err
117+
}
118+
}
119+
120+
// If option was specified in both args and config file, args will overwrite the config file.
121+
if len(args) == 1 {
122+
newK8sVersion = args[0]
136123
cfg.KubernetesVersion = newK8sVersion
137124
}
138125

cmd/kubeadm/app/cmd/upgrade/common_test.go

Lines changed: 1 addition & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -18,98 +18,11 @@ package upgrade
1818

1919
import (
2020
"bytes"
21-
"io/ioutil"
22-
"os"
2321
"testing"
2422

2523
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
26-
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
2724
)
2825

29-
func TestGetK8sVersionFromUserInput(t *testing.T) {
30-
currentVersion := "v" + constants.CurrentKubernetesVersion.String()
31-
validConfig := "apiVersion: kubeadm.k8s.io/v1beta2\n" +
32-
"kind: ClusterConfiguration\n" +
33-
"kubernetesVersion: " + currentVersion
34-
35-
var tcases = []struct {
36-
name string
37-
isVersionMandatory bool
38-
clusterConfig string
39-
args []string
40-
expectedErr bool
41-
expectedVersion string
42-
}{
43-
{
44-
name: "No config and version as an argument",
45-
isVersionMandatory: true,
46-
args: []string{"v1.13.1"},
47-
expectedVersion: "v1.13.1",
48-
},
49-
{
50-
name: "Neither config nor version specified",
51-
isVersionMandatory: true,
52-
expectedErr: true,
53-
},
54-
{
55-
name: "No config and empty version as an argument",
56-
isVersionMandatory: true,
57-
args: []string{""},
58-
expectedErr: true,
59-
},
60-
{
61-
name: "Valid config, but no version specified",
62-
isVersionMandatory: true,
63-
clusterConfig: validConfig,
64-
expectedVersion: currentVersion,
65-
},
66-
{
67-
name: "Valid config and different version specified",
68-
isVersionMandatory: true,
69-
clusterConfig: validConfig,
70-
args: []string{"v1.13.1"},
71-
expectedVersion: "v1.13.1",
72-
},
73-
{
74-
name: "Version is optional",
75-
},
76-
}
77-
for _, tt := range tcases {
78-
t.Run(tt.name, func(t *testing.T) {
79-
flags := &applyPlanFlags{}
80-
if len(tt.clusterConfig) > 0 {
81-
file, err := ioutil.TempFile("", "kubeadm-upgrade-common-test-*.yaml")
82-
if err != nil {
83-
t.Fatalf("Failed to create test config file: %+v", err)
84-
}
85-
86-
tmpFileName := file.Name()
87-
defer os.Remove(tmpFileName)
88-
89-
_, err = file.WriteString(tt.clusterConfig)
90-
file.Close()
91-
if err != nil {
92-
t.Fatalf("Failed to write test config file contents: %+v", err)
93-
}
94-
95-
flags.cfgPath = tmpFileName
96-
}
97-
98-
userVersion, err := getK8sVersionFromUserInput(flags, tt.args, tt.isVersionMandatory)
99-
100-
if err == nil && tt.expectedErr {
101-
t.Error("Expected error, but got success")
102-
}
103-
if err != nil && !tt.expectedErr {
104-
t.Errorf("Unexpected error: %+v", err)
105-
}
106-
if userVersion != tt.expectedVersion {
107-
t.Errorf("Expected %q, but got %q", tt.expectedVersion, userVersion)
108-
}
109-
})
110-
}
111-
}
112-
11326
func TestEnforceRequirements(t *testing.T) {
11427
tcases := []struct {
11528
name string
@@ -139,7 +52,7 @@ func TestEnforceRequirements(t *testing.T) {
13952
}
14053
for _, tt := range tcases {
14154
t.Run(tt.name, func(t *testing.T) {
142-
_, _, _, err := enforceRequirements(&tt.flags, tt.dryRun, tt.newK8sVersion)
55+
_, _, _, err := enforceRequirements(&tt.flags, nil, tt.dryRun, false)
14356

14457
if err == nil && tt.expectedErr {
14558
t.Error("Expected error, but got success")

cmd/kubeadm/app/cmd/upgrade/plan.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,7 @@ func NewCmdPlan(apf *applyPlanFlags) *cobra.Command {
4848
Use: "plan [version] [flags]",
4949
Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter",
5050
RunE: func(_ *cobra.Command, args []string) error {
51-
userVersion, err := getK8sVersionFromUserInput(flags.applyPlanFlags, args, false)
52-
if err != nil {
53-
return err
54-
}
55-
56-
return runPlan(flags, userVersion)
51+
return runPlan(flags, args)
5752
},
5853
}
5954

@@ -63,11 +58,11 @@ func NewCmdPlan(apf *applyPlanFlags) *cobra.Command {
6358
}
6459

6560
// runPlan takes care of outputting available versions to upgrade to for the user
66-
func runPlan(flags *planFlags, userVersion string) error {
61+
func runPlan(flags *planFlags, args []string) error {
6762
// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning.
6863
klog.V(1).Infoln("[upgrade/plan] verifying health of cluster")
6964
klog.V(1).Infoln("[upgrade/plan] retrieving configuration from cluster")
70-
client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, false, userVersion)
65+
client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, args, false, false)
7166
if err != nil {
7267
return err
7368
}

0 commit comments

Comments
 (0)