Skip to content

Commit 709e3c3

Browse files
committed
kubeadm upgrade plan: component config state table
This change enables kubeadm upgrade plan to print a state table with information regarding known component config API groups. Most importantly this information includes current and preferred version for each group and an indication if a manual user upgrade is required. Signed-off-by: Rostislav M. Georgiev <[email protected]>
1 parent 9d6e2b9 commit 709e3c3

File tree

10 files changed

+676
-2
lines changed

10 files changed

+676
-2
lines changed

cmd/kubeadm/app/apis/output/types.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ type ComponentUpgradePlan struct {
4848
NewVersion string
4949
}
5050

51+
// ComponentConfigVersionState describes the current and desired version of a component config
52+
type ComponentConfigVersionState struct {
53+
// Group points to the Kubernetes API group that covers the config
54+
Group string
55+
56+
// CurrentVersion is the currently active component config version
57+
// NOTE: This can be empty in case the config was not found on the cluster or it was unsupported
58+
// kubeadm generated version
59+
CurrentVersion string
60+
61+
// PreferredVersion is the component config version that is currently preferred by kubeadm for use.
62+
// NOTE: As of today, this is the only version supported by kubeadm.
63+
PreferredVersion string
64+
65+
// ManualUpgradeRequired indicates if users need to manually upgrade their component config versions. This happens if
66+
// the CurrentVersion of the config is user supplied (or modified) and no longer supported. Users should upgrade
67+
// their component configs to PreferredVersion or any other supported component config version.
68+
ManualUpgradeRequired bool
69+
}
70+
5171
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
5272

5373
// UpgradePlan represents information about upgrade plan for the output
@@ -56,4 +76,6 @@ type UpgradePlan struct {
5676
metav1.TypeMeta
5777

5878
Components []ComponentUpgradePlan
79+
80+
ConfigVersions []ComponentConfigVersionState
5981
}

cmd/kubeadm/app/apis/output/v1alpha1/types.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ type ComponentUpgradePlan struct {
4848
NewVersion string `json:"newVersion"`
4949
}
5050

51+
// ComponentConfigVersionState describes the current and desired version of a component config
52+
type ComponentConfigVersionState struct {
53+
// Group points to the Kubernetes API group that covers the config
54+
Group string `json:"group"`
55+
56+
// CurrentVersion is the currently active component config version
57+
// NOTE: This can be empty in case the config was not found on the cluster or it was unsupported
58+
// kubeadm generated version
59+
CurrentVersion string `json:"currentVersion"`
60+
61+
// PreferredVersion is the component config version that is currently preferred by kubeadm for use.
62+
// NOTE: As of today, this is the only version supported by kubeadm.
63+
PreferredVersion string `json:"preferredVersion"`
64+
65+
// ManualUpgradeRequired indicates if users need to manually upgrade their component config versions. This happens if
66+
// the CurrentVersion of the config is user supplied (or modified) and no longer supported. Users should upgrade
67+
// their component configs to PreferredVersion or any other supported component config version.
68+
ManualUpgradeRequired bool `json:"manualUpgradeRequired"`
69+
}
70+
5171
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
5272

5373
// UpgradePlan represents information about upgrade plan for the output
@@ -56,4 +76,6 @@ type UpgradePlan struct {
5676
metav1.TypeMeta
5777

5878
Components []ComponentUpgradePlan `json:"components"`
79+
80+
ConfigVersions []ComponentConfigVersionState `json:"configVersions"`
5981
}

cmd/kubeadm/app/apis/output/v1alpha1/zz_generated.conversion.go

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/kubeadm/app/apis/output/v1alpha1/zz_generated.deepcopy.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/kubeadm/app/apis/output/zz_generated.deepcopy.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/kubeadm/app/cmd/upgrade/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ go_library(
3838
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
3939
"//staging/src/k8s.io/client-go/discovery/fake:go_default_library",
4040
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
41+
"//vendor/github.com/lithammer/dedent:go_default_library",
4142
"//vendor/github.com/pkg/errors:go_default_library",
4243
"//vendor/github.com/pmezard/go-difflib/difflib:go_default_library",
4344
"//vendor/github.com/spf13/cobra:go_default_library",

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

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,25 @@ package upgrade
1919
import (
2020
"fmt"
2121
"io"
22+
"io/ioutil"
2223
"os"
2324
"sort"
2425
"strings"
2526
"text/tabwriter"
2627

28+
"github.com/lithammer/dedent"
2729
"github.com/pkg/errors"
2830
"github.com/spf13/cobra"
2931

3032
"k8s.io/apimachinery/pkg/util/version"
33+
clientset "k8s.io/client-go/kubernetes"
3134
"k8s.io/klog/v2"
3235
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3336
outputapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
37+
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
3438
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
3539
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
40+
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
3641
)
3742

3843
type planFlags struct {
@@ -79,6 +84,13 @@ func runPlan(flags *planFlags, args []string) error {
7984
return errors.Wrap(err, "[upgrade/versions] FATAL")
8085
}
8186

87+
// Fetch the current state of the component configs
88+
klog.V(1).Infoln("[upgrade/plan] analysing component config version states")
89+
configVersionStates, err := getComponentConfigVersionStates(&cfg.ClusterConfiguration, client, flags.cfgPath)
90+
if err != nil {
91+
return errors.WithMessage(err, "[upgrade/versions] FATAL")
92+
}
93+
8294
// No upgrades available
8395
if len(availUpgrades) == 0 {
8496
klog.V(1).Infoln("[upgrade/plan] Awesome, you're up-to-date! Enjoy!")
@@ -92,8 +104,17 @@ func runPlan(flags *planFlags, args []string) error {
92104
return err
93105
}
94106

107+
// Actually, this is needed for machine readable output only.
108+
// printUpgradePlan won't output the configVersionStates as it will simply print the same table several times
109+
// in the human readable output if it did so
110+
plan.ConfigVersions = configVersionStates
111+
95112
printUpgradePlan(&up, plan, unstableVersionFlag, isExternalEtcd, os.Stdout)
96113
}
114+
115+
// Finally, print the component config state table
116+
printComponentConfigVersionStates(configVersionStates, os.Stdout)
117+
97118
return nil
98119
}
99120

@@ -165,6 +186,24 @@ func genUpgradePlan(up *upgrade.Upgrade, isExternalEtcd bool) (*outputapi.Upgrad
165186
return &outputapi.UpgradePlan{Components: components}, unstableVersionFlag, nil
166187
}
167188

189+
func getComponentConfigVersionStates(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, cfgPath string) ([]outputapi.ComponentConfigVersionState, error) {
190+
docmap := kubeadmapi.DocumentMap{}
191+
192+
if cfgPath != "" {
193+
bytes, err := ioutil.ReadFile(cfgPath)
194+
if err != nil {
195+
return nil, errors.Wrapf(err, "unable to read config file %q", cfgPath)
196+
}
197+
198+
docmap, err = kubeadmutil.SplitYAMLDocuments(bytes)
199+
if err != nil {
200+
return nil, err
201+
}
202+
}
203+
204+
return componentconfigs.GetVersionStates(cfg, client, docmap)
205+
}
206+
168207
// printUpgradePlan prints a UX-friendly overview of what versions are available to upgrade to
169208
func printUpgradePlan(up *upgrade.Upgrade, plan *outputapi.UpgradePlan, unstableVersionFlag string, isExternalEtcd bool, w io.Writer) {
170209
// The tab writer writes to the "real" writer w
@@ -218,8 +257,7 @@ func printUpgradePlan(up *upgrade.Upgrade, plan *outputapi.UpgradePlan, unstable
218257
fmt.Fprintln(w, "")
219258
}
220259

221-
fmt.Fprintln(w, "_____________________________________________________________________")
222-
fmt.Fprintln(w, "")
260+
printLineSeparator(w)
223261
}
224262

225263
// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
@@ -231,3 +269,52 @@ func sortedSliceFromStringIntMap(strMap map[string]uint16) []string {
231269
sort.Strings(strSlice)
232270
return strSlice
233271
}
272+
273+
func strOrDash(s string) string {
274+
if s != "" {
275+
return s
276+
}
277+
return "-"
278+
}
279+
280+
func yesOrNo(b bool) string {
281+
if b {
282+
return "yes"
283+
}
284+
return "no"
285+
}
286+
287+
func printLineSeparator(w io.Writer) {
288+
fmt.Fprintln(w, "_____________________________________________________________________")
289+
fmt.Fprintln(w, "")
290+
}
291+
292+
func printComponentConfigVersionStates(versionStates []outputapi.ComponentConfigVersionState, w io.Writer) {
293+
if len(versionStates) == 0 {
294+
fmt.Fprintln(w, "No information available on component configs.")
295+
return
296+
}
297+
298+
fmt.Fprintln(w, dedent.Dedent(`
299+
The table below shows the current state of component configs as understood by this version of kubeadm.
300+
Configs that have a "yes" mark in the "MANUAL UPGRADE REQUIRED" column require manual config upgrade or
301+
resetting to kubeadm defaults before a successful upgrade can be performed. The version to manually
302+
upgrade to is denoted in the "PREFERRED VERSION" column.
303+
`))
304+
305+
tabw := tabwriter.NewWriter(w, 10, 4, 3, ' ', 0)
306+
fmt.Fprintln(tabw, "API GROUP\tCURRENT VERSION\tPREFERRED VERSION\tMANUAL UPGRADE REQUIRED")
307+
308+
for _, state := range versionStates {
309+
fmt.Fprintf(tabw,
310+
"%s\t%s\t%s\t%s\n",
311+
state.Group,
312+
strOrDash(state.CurrentVersion),
313+
strOrDash(state.PreferredVersion),
314+
yesOrNo(state.ManualUpgradeRequired),
315+
)
316+
}
317+
318+
tabw.Flush()
319+
printLineSeparator(w)
320+
}

cmd/kubeadm/app/componentconfigs/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ go_library(
1515
deps = [
1616
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
1717
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
18+
"//cmd/kubeadm/app/apis/output:go_default_library",
1819
"//cmd/kubeadm/app/constants:go_default_library",
1920
"//cmd/kubeadm/app/features:go_default_library",
2021
"//cmd/kubeadm/app/util:go_default_library",
@@ -51,6 +52,7 @@ go_test(
5152
deps = [
5253
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
5354
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
55+
"//cmd/kubeadm/app/apis/output:go_default_library",
5456
"//cmd/kubeadm/app/constants:go_default_library",
5557
"//cmd/kubeadm/app/features:go_default_library",
5658
"//cmd/kubeadm/app/util:go_default_library",

0 commit comments

Comments
 (0)