mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 03:33:56 +00:00
print nodename
This commit is contained in:
parent
210378e918
commit
22adf221a1
@ -49,6 +49,7 @@ type ComponentUpgradePlan struct {
|
|||||||
Name string
|
Name string
|
||||||
CurrentVersion string
|
CurrentVersion string
|
||||||
NewVersion string
|
NewVersion string
|
||||||
|
NodeName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComponentConfigVersionState describes the current and desired version of a component config
|
// ComponentConfigVersionState describes the current and desired version of a component config
|
||||||
|
@ -26,3 +26,8 @@ import (
|
|||||||
func Convert_output_UpgradePlan_To_v1alpha2_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
|
func Convert_output_UpgradePlan_To_v1alpha2_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
|
||||||
return autoConvert_output_UpgradePlan_To_v1alpha2_UpgradePlan(in, out, s)
|
return autoConvert_output_UpgradePlan_To_v1alpha2_UpgradePlan(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan converts a private ComponentUpgradePlan to public ComponentUpgradePlan.
|
||||||
|
func Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(in *output.ComponentUpgradePlan, out *ComponentUpgradePlan, s conversion.Scope) error {
|
||||||
|
return autoConvert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(in, out, s)
|
||||||
|
}
|
||||||
|
@ -61,11 +61,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*output.ComponentUpgradePlan)(nil), (*ComponentUpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(a.(*output.ComponentUpgradePlan), b.(*ComponentUpgradePlan), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*Images)(nil), (*output.Images)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*Images)(nil), (*output.Images)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_v1alpha2_Images_To_output_Images(a.(*Images), b.(*output.Images), scope)
|
return Convert_v1alpha2_Images_To_output_Images(a.(*Images), b.(*output.Images), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -81,6 +76,11 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := s.AddConversionFunc((*output.ComponentUpgradePlan)(nil), (*ComponentUpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(a.(*output.ComponentUpgradePlan), b.(*ComponentUpgradePlan), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := s.AddConversionFunc((*output.UpgradePlan)(nil), (*UpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddConversionFunc((*output.UpgradePlan)(nil), (*UpgradePlan)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_output_UpgradePlan_To_v1alpha2_UpgradePlan(a.(*output.UpgradePlan), b.(*UpgradePlan), scope)
|
return Convert_output_UpgradePlan_To_v1alpha2_UpgradePlan(a.(*output.UpgradePlan), b.(*UpgradePlan), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -151,14 +151,10 @@ func autoConvert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(in
|
|||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.CurrentVersion = in.CurrentVersion
|
out.CurrentVersion = in.CurrentVersion
|
||||||
out.NewVersion = in.NewVersion
|
out.NewVersion = in.NewVersion
|
||||||
|
// WARNING: in.NodeName requires manual conversion: does not exist in peer-type
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan is an autogenerated conversion function.
|
|
||||||
func Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(in *output.ComponentUpgradePlan, out *ComponentUpgradePlan, s conversion.Scope) error {
|
|
||||||
return autoConvert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_v1alpha2_Images_To_output_Images(in *Images, out *output.Images, s conversion.Scope) error {
|
func autoConvert_v1alpha2_Images_To_output_Images(in *Images, out *output.Images, s conversion.Scope) error {
|
||||||
out.Images = *(*[]string)(unsafe.Pointer(&in.Images))
|
out.Images = *(*[]string)(unsafe.Pointer(&in.Images))
|
||||||
return nil
|
return nil
|
||||||
@ -180,7 +176,17 @@ func Convert_output_Images_To_v1alpha2_Images(in *output.Images, out *Images, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1alpha2_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *output.UpgradePlan, s conversion.Scope) error {
|
func autoConvert_v1alpha2_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *output.UpgradePlan, s conversion.Scope) error {
|
||||||
out.Components = *(*[]output.ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
|
if in.Components != nil {
|
||||||
|
in, out := &in.Components, &out.Components
|
||||||
|
*out = make([]output.ComponentUpgradePlan, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
if err := Convert_v1alpha2_ComponentUpgradePlan_To_output_ComponentUpgradePlan(&(*in)[i], &(*out)[i], s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Components = nil
|
||||||
|
}
|
||||||
out.ConfigVersions = *(*[]output.ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
|
out.ConfigVersions = *(*[]output.ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -193,6 +199,16 @@ func Convert_v1alpha2_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *ou
|
|||||||
func autoConvert_output_UpgradePlan_To_v1alpha2_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
|
func autoConvert_output_UpgradePlan_To_v1alpha2_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
|
||||||
// WARNING: in.AvailableUpgrades requires manual conversion: does not exist in peer-type
|
// WARNING: in.AvailableUpgrades requires manual conversion: does not exist in peer-type
|
||||||
out.ConfigVersions = *(*[]ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
|
out.ConfigVersions = *(*[]ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
|
||||||
out.Components = *(*[]ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
|
if in.Components != nil {
|
||||||
|
in, out := &in.Components, &out.Components
|
||||||
|
*out = make([]ComponentUpgradePlan, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
if err := Convert_output_ComponentUpgradePlan_To_v1alpha2_ComponentUpgradePlan(&(*in)[i], &(*out)[i], s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Components = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ type ComponentUpgradePlan struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CurrentVersion string `json:"currentVersion"`
|
CurrentVersion string `json:"currentVersion"`
|
||||||
NewVersion string `json:"newVersion"`
|
NewVersion string `json:"newVersion"`
|
||||||
|
NodeName string `json:"nodeName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComponentConfigVersionState describes the current and desired version of a component config
|
// ComponentConfigVersionState describes the current and desired version of a component config
|
||||||
|
@ -243,6 +243,7 @@ func autoConvert_v1alpha3_ComponentUpgradePlan_To_output_ComponentUpgradePlan(in
|
|||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.CurrentVersion = in.CurrentVersion
|
out.CurrentVersion = in.CurrentVersion
|
||||||
out.NewVersion = in.NewVersion
|
out.NewVersion = in.NewVersion
|
||||||
|
out.NodeName = in.NodeName
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +256,7 @@ func autoConvert_output_ComponentUpgradePlan_To_v1alpha3_ComponentUpgradePlan(in
|
|||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.CurrentVersion = in.CurrentVersion
|
out.CurrentVersion = in.CurrentVersion
|
||||||
out.NewVersion = in.NewVersion
|
out.NewVersion = in.NewVersion
|
||||||
|
out.NodeName = in.NodeName
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package upgrade
|
package upgrade
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
@ -88,11 +87,12 @@ func newCmdPlan(apf *applyPlanFlags) *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newComponentUpgradePlan helper creates outputapiv1alpha3.ComponentUpgradePlan object
|
// newComponentUpgradePlan helper creates outputapiv1alpha3.ComponentUpgradePlan object
|
||||||
func newComponentUpgradePlan(name, currentVersion, newVersion string) outputapiv1alpha3.ComponentUpgradePlan {
|
func newComponentUpgradePlan(name, currentVersion, newVersion, nodeName string) outputapiv1alpha3.ComponentUpgradePlan {
|
||||||
return outputapiv1alpha3.ComponentUpgradePlan{
|
return outputapiv1alpha3.ComponentUpgradePlan{
|
||||||
Name: name,
|
Name: name,
|
||||||
CurrentVersion: currentVersion,
|
CurrentVersion: currentVersion,
|
||||||
NewVersion: newVersion,
|
NewVersion: newVersion,
|
||||||
|
NodeName: nodeName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,10 +106,6 @@ func runPlan(flagSet *pflag.FlagSet, flags *planFlags, args []string, printer ou
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently this is the only method we have for distinguishing
|
|
||||||
// external etcd vs static pod etcd
|
|
||||||
isExternalEtcd := initCfg.Etcd.External != nil
|
|
||||||
|
|
||||||
// Compute which upgrade possibilities there are
|
// Compute which upgrade possibilities there are
|
||||||
klog.V(1).Infoln("[upgrade/plan] computing upgrade possibilities")
|
klog.V(1).Infoln("[upgrade/plan] computing upgrade possibilities")
|
||||||
|
|
||||||
@ -124,7 +120,7 @@ func runPlan(flagSet *pflag.FlagSet, flags *planFlags, args []string, printer ou
|
|||||||
return cmdutil.TypeMismatchErr("allowExperimentalUpgrades", "bool")
|
return cmdutil.TypeMismatchErr("allowExperimentalUpgrades", "bool")
|
||||||
}
|
}
|
||||||
|
|
||||||
availUpgrades, err := upgrade.GetAvailableUpgrades(versionGetter, *allowExperimentalUpgrades, *allowRCUpgrades, isExternalEtcd, client, constants.GetStaticPodDirectory(), printer)
|
availUpgrades, err := upgrade.GetAvailableUpgrades(versionGetter, *allowExperimentalUpgrades, *allowRCUpgrades, client, printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "[upgrade/versions] FATAL")
|
return errors.Wrap(err, "[upgrade/versions] FATAL")
|
||||||
}
|
}
|
||||||
@ -143,16 +139,15 @@ func runPlan(flagSet *pflag.FlagSet, flags *planFlags, args []string, printer ou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate and print the upgrade plan
|
// Generate and print the upgrade plan
|
||||||
plan := genUpgradePlan(availUpgrades, configVersionStates, isExternalEtcd)
|
plan := genUpgradePlan(availUpgrades, configVersionStates)
|
||||||
return printer.PrintObj(plan, os.Stdout)
|
return printer.PrintObj(plan, os.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// genUpgradePlan generates upgrade plan from available upgrades and component config version states
|
// genUpgradePlan generates upgrade plan from available upgrades and component config version states
|
||||||
func genUpgradePlan(availUpgrades []upgrade.Upgrade, configVersions []outputapiv1alpha3.ComponentConfigVersionState, isExternalEtcd bool) *outputapiv1alpha3.UpgradePlan {
|
func genUpgradePlan(availUpgrades []upgrade.Upgrade, configVersions []outputapiv1alpha3.ComponentConfigVersionState) *outputapiv1alpha3.UpgradePlan {
|
||||||
plan := &outputapiv1alpha3.UpgradePlan{ConfigVersions: configVersions}
|
plan := &outputapiv1alpha3.UpgradePlan{ConfigVersions: configVersions}
|
||||||
for _, up := range availUpgrades {
|
for _, up := range availUpgrades {
|
||||||
au := genAvailableUpgrade(&up, isExternalEtcd)
|
plan.AvailableUpgrades = append(plan.AvailableUpgrades, genAvailableUpgrade(&up))
|
||||||
plan.AvailableUpgrades = append(plan.AvailableUpgrades, au)
|
|
||||||
}
|
}
|
||||||
return plan
|
return plan
|
||||||
}
|
}
|
||||||
@ -164,7 +159,7 @@ func appendDNSComponent(components []outputapiv1alpha3.ComponentUpgradePlan, up
|
|||||||
afterVersion := up.After.DNSVersion
|
afterVersion := up.After.DNSVersion
|
||||||
|
|
||||||
if beforeVersion != "" || afterVersion != "" {
|
if beforeVersion != "" || afterVersion != "" {
|
||||||
components = append(components, newComponentUpgradePlan(name, beforeVersion, afterVersion))
|
components = append(components, newComponentUpgradePlan(name, beforeVersion, afterVersion, ""))
|
||||||
}
|
}
|
||||||
return components
|
return components
|
||||||
}
|
}
|
||||||
@ -175,41 +170,64 @@ func appendKubeadmComponent(components []outputapiv1alpha3.ComponentUpgradePlan,
|
|||||||
afterVersion := up.After.KubeadmVersion
|
afterVersion := up.After.KubeadmVersion
|
||||||
|
|
||||||
if beforeVersion != "" || afterVersion != "" {
|
if beforeVersion != "" || afterVersion != "" {
|
||||||
components = append(components, newComponentUpgradePlan(name, beforeVersion, afterVersion))
|
components = append(components, newComponentUpgradePlan(name, beforeVersion, afterVersion, ""))
|
||||||
}
|
}
|
||||||
return components
|
return components
|
||||||
}
|
}
|
||||||
|
|
||||||
// genAvailableUpgrade generates available upgrade from upgrade object and external etcd boolean
|
// genAvailableUpgrade generates available upgrade from upgrade object.
|
||||||
func genAvailableUpgrade(up *upgrade.Upgrade, isExternalEtcd bool) outputapiv1alpha3.AvailableUpgrade {
|
func genAvailableUpgrade(up *upgrade.Upgrade) outputapiv1alpha3.AvailableUpgrade {
|
||||||
components := []outputapiv1alpha3.ComponentUpgradePlan{}
|
components := []outputapiv1alpha3.ComponentUpgradePlan{}
|
||||||
|
|
||||||
if up.CanUpgradeKubelets() {
|
if up.CanUpgradeKubelets() {
|
||||||
// The map is of the form <old-version>:<node-count>. Here all the keys are put into a slice and sorted
|
// The map is of the form <old-version>:<node-names>. Here all the keys are put into a slice and sorted
|
||||||
// in order to always get the right order. Then the map value is extracted separately
|
// in order to always get the right order. Then the map value is extracted separately
|
||||||
for _, oldVersion := range sortedSliceFromStringIntMap(up.Before.KubeletVersions) {
|
for _, oldVersion := range sortedSliceFromStringStringArrayMap(up.Before.KubeletVersions) {
|
||||||
nodeCount := up.Before.KubeletVersions[oldVersion]
|
nodeNames := up.Before.KubeletVersions[oldVersion]
|
||||||
components = append(components, newComponentUpgradePlan(constants.Kubelet, fmt.Sprintf("%d x %s", nodeCount, oldVersion), up.After.KubeVersion))
|
for _, nodeName := range nodeNames {
|
||||||
|
components = append(components, newComponentUpgradePlan(constants.Kubelet, oldVersion, up.After.KubeVersion, nodeName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
components = append(components, newComponentUpgradePlan(constants.KubeAPIServer, up.Before.KubeVersion, up.After.KubeVersion))
|
for _, oldVersion := range sortedSliceFromStringStringArrayMap(up.Before.KubeAPIServerVersions) {
|
||||||
components = append(components, newComponentUpgradePlan(constants.KubeControllerManager, up.Before.KubeVersion, up.After.KubeVersion))
|
nodeNames := up.Before.KubeAPIServerVersions[oldVersion]
|
||||||
components = append(components, newComponentUpgradePlan(constants.KubeScheduler, up.Before.KubeVersion, up.After.KubeVersion))
|
for _, nodeName := range nodeNames {
|
||||||
components = append(components, newComponentUpgradePlan(constants.KubeProxy, up.Before.KubeVersion, up.After.KubeVersion))
|
components = append(components, newComponentUpgradePlan(constants.KubeAPIServer, oldVersion, up.After.KubeVersion, nodeName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, oldVersion := range sortedSliceFromStringStringArrayMap(up.Before.KubeControllerManagerVersions) {
|
||||||
|
nodeNames := up.Before.KubeControllerManagerVersions[oldVersion]
|
||||||
|
for _, nodeName := range nodeNames {
|
||||||
|
components = append(components, newComponentUpgradePlan(constants.KubeControllerManager, oldVersion, up.After.KubeVersion, nodeName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, oldVersion := range sortedSliceFromStringStringArrayMap(up.Before.KubeSchedulerVersions) {
|
||||||
|
nodeNames := up.Before.KubeSchedulerVersions[oldVersion]
|
||||||
|
for _, nodeName := range nodeNames {
|
||||||
|
components = append(components, newComponentUpgradePlan(constants.KubeScheduler, oldVersion, up.After.KubeVersion, nodeName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
components = append(components, newComponentUpgradePlan(constants.KubeProxy, up.Before.KubeVersion, up.After.KubeVersion, ""))
|
||||||
components = appendDNSComponent(components, up, constants.CoreDNS)
|
components = appendDNSComponent(components, up, constants.CoreDNS)
|
||||||
components = appendKubeadmComponent(components, up, constants.Kubeadm)
|
components = appendKubeadmComponent(components, up, constants.Kubeadm)
|
||||||
|
|
||||||
if !isExternalEtcd {
|
// If etcd is not external, we should include it in the upgrade plan
|
||||||
components = append(components, newComponentUpgradePlan(constants.Etcd, up.Before.EtcdVersion, up.After.EtcdVersion))
|
for _, oldVersion := range sortedSliceFromStringStringArrayMap(up.Before.EtcdVersions) {
|
||||||
|
nodeNames := up.Before.EtcdVersions[oldVersion]
|
||||||
|
for _, nodeName := range nodeNames {
|
||||||
|
components = append(components, newComponentUpgradePlan(constants.Etcd, oldVersion, up.After.EtcdVersion, nodeName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputapiv1alpha3.AvailableUpgrade{Description: up.Description, Components: components}
|
return outputapiv1alpha3.AvailableUpgrade{Description: up.Description, Components: components}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
|
// sortedSliceFromStringStringArrayMap returns a slice of the keys in the map sorted alphabetically
|
||||||
func sortedSliceFromStringIntMap(strMap map[string]uint16) []string {
|
func sortedSliceFromStringStringArrayMap(strMap map[string][]string) []string {
|
||||||
strSlice := []string{}
|
strSlice := []string{}
|
||||||
for k := range strMap {
|
for k := range strMap {
|
||||||
strSlice = append(strSlice, k)
|
strSlice = append(strSlice, k)
|
||||||
@ -280,28 +298,24 @@ func (printer *upgradePlanTextPrinter) printAvailableUpgrade(writer io.Writer, a
|
|||||||
|
|
||||||
_, _ = printer.Fprintln(writer, "Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':")
|
_, _ = printer.Fprintln(writer, "Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':")
|
||||||
tabw := tabwriter.NewWriter(writer, 10, 4, 3, ' ', 0)
|
tabw := tabwriter.NewWriter(writer, 10, 4, 3, ' ', 0)
|
||||||
_, _ = printer.Fprintln(tabw, strings.Join([]string{"COMPONENT", "CURRENT", "TARGET"}, "\t"))
|
_, _ = printer.Fprintln(tabw, strings.Join([]string{"COMPONENT", "NODE", "CURRENT", "TARGET"}, "\t"))
|
||||||
for i, component := range au.Components {
|
for _, component := range au.Components {
|
||||||
if component.Name != constants.Kubelet {
|
if component.Name != constants.Kubelet {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if i == 0 {
|
_, _ = printer.Fprintf(tabw, "%s\t%s\t%s\t%s\n", component.Name, component.NodeName, component.CurrentVersion, component.NewVersion)
|
||||||
_, _ = printer.Fprintf(tabw, "%s\t%s\t%s\n", component.Name, component.CurrentVersion, component.NewVersion)
|
|
||||||
} else {
|
|
||||||
_, _ = printer.Fprintf(tabw, "%s\t%s\t%s\n", "", component.CurrentVersion, component.NewVersion)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ = tabw.Flush()
|
_ = tabw.Flush()
|
||||||
|
|
||||||
_, _ = printer.Fprintln(writer, "")
|
_, _ = printer.Fprintln(writer, "")
|
||||||
_, _ = printer.Fprintf(writer, "Upgrade to the latest %s:\n", au.Description)
|
_, _ = printer.Fprintf(writer, "Upgrade to the latest %s:\n", au.Description)
|
||||||
_, _ = printer.Fprintln(writer, "")
|
_, _ = printer.Fprintln(writer, "")
|
||||||
_, _ = printer.Fprintln(tabw, strings.Join([]string{"COMPONENT", "CURRENT", "TARGET"}, "\t"))
|
_, _ = printer.Fprintln(tabw, strings.Join([]string{"COMPONENT", "NODE", "CURRENT", "TARGET"}, "\t"))
|
||||||
for _, component := range au.Components {
|
for _, component := range au.Components {
|
||||||
if component.Name == constants.Kubelet || component.Name == constants.Kubeadm {
|
if component.Name == constants.Kubelet || component.Name == constants.Kubeadm {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, _ = printer.Fprintf(tabw, "%s\t%s\t%s\n", component.Name, component.CurrentVersion, component.NewVersion)
|
_, _ = printer.Fprintf(tabw, "%s\t%s\t%s\t%s\n", component.Name, component.NodeName, component.CurrentVersion, component.NewVersion)
|
||||||
}
|
}
|
||||||
_ = tabw.Flush()
|
_ = tabw.Flush()
|
||||||
|
|
||||||
|
@ -28,39 +28,39 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSortedSliceFromStringIntMap(t *testing.T) {
|
func TestSortedSliceFromStringStringArrayMap(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
name string
|
name string
|
||||||
strMap map[string]uint16
|
strMap map[string][]string
|
||||||
expectedSlice []string
|
expectedSlice []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "the returned slice should be alphabetically sorted based on the string keys in the map",
|
name: "the returned slice should be alphabetically sorted based on the string keys in the map",
|
||||||
strMap: map[string]uint16{"foo": 1, "bar": 2},
|
strMap: map[string][]string{"foo": {"1"}, "bar": {"1", "2"}},
|
||||||
expectedSlice: []string{"bar", "foo"},
|
expectedSlice: []string{"bar", "foo"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "the int value should not affect this func",
|
name: "the int value should not affect this func",
|
||||||
strMap: map[string]uint16{"foo": 2, "bar": 1},
|
strMap: map[string][]string{"foo": {"1", "2"}, "bar": {"1"}},
|
||||||
expectedSlice: []string{"bar", "foo"},
|
expectedSlice: []string{"bar", "foo"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "slice with 4 keys and different values",
|
name: "slice with 4 keys and different values",
|
||||||
strMap: map[string]uint16{"b": 2, "a": 1, "cb": 0, "ca": 1000},
|
strMap: map[string][]string{"b": {"1", "2"}, "a": {"1"}, "cb": {}, "ca": {"1", "2", "3"}},
|
||||||
expectedSlice: []string{"a", "b", "ca", "cb"},
|
expectedSlice: []string{"a", "b", "ca", "cb"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "this should work for version numbers as well; and the lowest version should come first",
|
name: "this should work for version numbers as well; and the lowest version should come first",
|
||||||
strMap: map[string]uint16{"v1.7.0": 1, "v1.6.1": 1, "v1.6.2": 1, "v1.8.0": 1, "v1.8.0-alpha.1": 1},
|
strMap: map[string][]string{"v1.7.0": {"1"}, "v1.6.1": {"1"}, "v1.6.2": {"1"}, "v1.8.0": {"1"}, "v1.8.0-alpha.1": {"1"}},
|
||||||
expectedSlice: []string{"v1.6.1", "v1.6.2", "v1.7.0", "v1.8.0", "v1.8.0-alpha.1"},
|
expectedSlice: []string{"v1.6.1", "v1.6.2", "v1.7.0", "v1.8.0", "v1.8.0-alpha.1"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
t.Run(rt.name, func(t *testing.T) {
|
t.Run(rt.name, func(t *testing.T) {
|
||||||
actualSlice := sortedSliceFromStringIntMap(rt.strMap)
|
actualSlice := sortedSliceFromStringStringArrayMap(rt.strMap)
|
||||||
if !reflect.DeepEqual(actualSlice, rt.expectedSlice) {
|
if !reflect.DeepEqual(actualSlice, rt.expectedSlice) {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed SortedSliceFromStringIntMap:\n\texpected: %v\n\t actual: %v",
|
"failed sortedSliceFromStringStringArrayMap:\n\texpected: %v\n\t actual: %v",
|
||||||
rt.expectedSlice,
|
rt.expectedSlice,
|
||||||
actualSlice,
|
actualSlice,
|
||||||
)
|
)
|
||||||
@ -101,12 +101,23 @@ func TestPrintUpgradePlan(t *testing.T) {
|
|||||||
Description: "version in the v1.18 series",
|
Description: "version in the v1.18 series",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.1",
|
KubeVersion: "v1.18.1",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.18.1": 1,
|
"v1.18.1": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.18.1": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.18.1": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.18.1": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.3-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.18.1",
|
KubeadmVersion: "v1.18.1",
|
||||||
DNSVersion: "1.6.7",
|
DNSVersion: "1.6.7",
|
||||||
EtcdVersion: "3.4.3-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.4",
|
KubeVersion: "v1.18.4",
|
||||||
@ -118,18 +129,18 @@ func TestPrintUpgradePlan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
versionStates: versionStates,
|
versionStates: versionStates,
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.18.1 v1.18.4
|
kubelet node1 v1.18.1 v1.18.4
|
||||||
|
|
||||||
Upgrade to the latest version in the v1.18 series:
|
Upgrade to the latest version in the v1.18 series:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.18.1 v1.18.4
|
kube-apiserver node1 v1.18.1 v1.18.4
|
||||||
kube-controller-manager v1.18.1 v1.18.4
|
kube-controller-manager node1 v1.18.1 v1.18.4
|
||||||
kube-scheduler v1.18.1 v1.18.4
|
kube-scheduler node1 v1.18.1 v1.18.4
|
||||||
kube-proxy v1.18.1 v1.18.4
|
kube-proxy v1.18.1 v1.18.4
|
||||||
CoreDNS 1.6.7 1.6.7
|
CoreDNS 1.6.7 1.6.7
|
||||||
etcd 3.4.3-0 3.4.3-0
|
etcd node1 3.4.3-0 3.4.3-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -159,12 +170,23 @@ _____________________________________________________________________
|
|||||||
Description: "stable version",
|
Description: "stable version",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.4",
|
KubeVersion: "v1.18.4",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.18.4": 1,
|
"v1.18.4": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.18.4": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.18.4": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.18.4": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.3-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.18.4",
|
KubeadmVersion: "v1.18.4",
|
||||||
DNSVersion: "1.6.7",
|
DNSVersion: "1.6.7",
|
||||||
EtcdVersion: "3.4.3-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.19.0",
|
KubeVersion: "v1.19.0",
|
||||||
@ -176,18 +198,18 @@ _____________________________________________________________________
|
|||||||
},
|
},
|
||||||
versionStates: versionStates,
|
versionStates: versionStates,
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.18.4 v1.19.0
|
kubelet node1 v1.18.4 v1.19.0
|
||||||
|
|
||||||
Upgrade to the latest stable version:
|
Upgrade to the latest stable version:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.18.4 v1.19.0
|
kube-apiserver node1 v1.18.4 v1.19.0
|
||||||
kube-controller-manager v1.18.4 v1.19.0
|
kube-controller-manager node1 v1.18.4 v1.19.0
|
||||||
kube-scheduler v1.18.4 v1.19.0
|
kube-scheduler node1 v1.18.4 v1.19.0
|
||||||
kube-proxy v1.18.4 v1.19.0
|
kube-proxy v1.18.4 v1.19.0
|
||||||
CoreDNS 1.6.7 1.7.0
|
CoreDNS 1.6.7 1.7.0
|
||||||
etcd 3.4.3-0 3.4.7-0
|
etcd node1 3.4.3-0 3.4.7-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -217,12 +239,23 @@ _____________________________________________________________________
|
|||||||
Description: "version in the v1.18 series",
|
Description: "version in the v1.18 series",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.3",
|
KubeVersion: "v1.18.3",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.18.3": 1,
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.3-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.18.3",
|
KubeadmVersion: "v1.18.3",
|
||||||
DNSVersion: "1.6.7",
|
DNSVersion: "1.6.7",
|
||||||
EtcdVersion: "3.4.3-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.5",
|
KubeVersion: "v1.18.5",
|
||||||
@ -235,12 +268,23 @@ _____________________________________________________________________
|
|||||||
Description: "stable version",
|
Description: "stable version",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.3",
|
KubeVersion: "v1.18.3",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.18.3": 1,
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.18.3": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.3-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.18.3",
|
KubeadmVersion: "v1.18.3",
|
||||||
DNSVersion: "1.6.7",
|
DNSVersion: "1.6.7",
|
||||||
EtcdVersion: "3.4.3-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.19.0",
|
KubeVersion: "v1.19.0",
|
||||||
@ -252,18 +296,18 @@ _____________________________________________________________________
|
|||||||
},
|
},
|
||||||
versionStates: versionStates,
|
versionStates: versionStates,
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.18.3 v1.18.5
|
kubelet node1 v1.18.3 v1.18.5
|
||||||
|
|
||||||
Upgrade to the latest version in the v1.18 series:
|
Upgrade to the latest version in the v1.18 series:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.18.3 v1.18.5
|
kube-apiserver node1 v1.18.3 v1.18.5
|
||||||
kube-controller-manager v1.18.3 v1.18.5
|
kube-controller-manager node1 v1.18.3 v1.18.5
|
||||||
kube-scheduler v1.18.3 v1.18.5
|
kube-scheduler node1 v1.18.3 v1.18.5
|
||||||
kube-proxy v1.18.3 v1.18.5
|
kube-proxy v1.18.3 v1.18.5
|
||||||
CoreDNS 1.6.7 1.6.7
|
CoreDNS 1.6.7 1.6.7
|
||||||
etcd 3.4.3-0 3.4.3-0
|
etcd node1 3.4.3-0 3.4.3-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -272,18 +316,18 @@ You can now apply the upgrade by executing the following command:
|
|||||||
_____________________________________________________________________
|
_____________________________________________________________________
|
||||||
|
|
||||||
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.18.3 v1.19.0
|
kubelet node1 v1.18.3 v1.19.0
|
||||||
|
|
||||||
Upgrade to the latest stable version:
|
Upgrade to the latest stable version:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.18.3 v1.19.0
|
kube-apiserver node1 v1.18.3 v1.19.0
|
||||||
kube-controller-manager v1.18.3 v1.19.0
|
kube-controller-manager node1 v1.18.3 v1.19.0
|
||||||
kube-scheduler v1.18.3 v1.19.0
|
kube-scheduler node1 v1.18.3 v1.19.0
|
||||||
kube-proxy v1.18.3 v1.19.0
|
kube-proxy v1.18.3 v1.19.0
|
||||||
CoreDNS 1.6.7 1.7.0
|
CoreDNS 1.6.7 1.7.0
|
||||||
etcd 3.4.3-0 3.4.7-0
|
etcd node1 3.4.3-0 3.4.7-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -313,12 +357,23 @@ _____________________________________________________________________
|
|||||||
Description: "experimental version",
|
Description: "experimental version",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.5",
|
KubeVersion: "v1.18.5",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.18.5": 1,
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.3-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.18.5",
|
KubeadmVersion: "v1.18.5",
|
||||||
DNSVersion: "1.6.7",
|
DNSVersion: "1.6.7",
|
||||||
EtcdVersion: "3.4.3-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.19.0-beta.1",
|
KubeVersion: "v1.19.0-beta.1",
|
||||||
@ -330,18 +385,18 @@ _____________________________________________________________________
|
|||||||
},
|
},
|
||||||
versionStates: versionStates,
|
versionStates: versionStates,
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.18.5 v1.19.0-beta.1
|
kubelet node1 v1.18.5 v1.19.0-beta.1
|
||||||
|
|
||||||
Upgrade to the latest experimental version:
|
Upgrade to the latest experimental version:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.18.5 v1.19.0-beta.1
|
kube-apiserver node1 v1.18.5 v1.19.0-beta.1
|
||||||
kube-controller-manager v1.18.5 v1.19.0-beta.1
|
kube-controller-manager node1 v1.18.5 v1.19.0-beta.1
|
||||||
kube-scheduler v1.18.5 v1.19.0-beta.1
|
kube-scheduler node1 v1.18.5 v1.19.0-beta.1
|
||||||
kube-proxy v1.18.5 v1.19.0-beta.1
|
kube-proxy v1.18.5 v1.19.0-beta.1
|
||||||
CoreDNS 1.6.7 1.7.0
|
CoreDNS 1.6.7 1.7.0
|
||||||
etcd 3.4.3-0 3.4.7-0
|
etcd node1 3.4.3-0 3.4.7-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -371,12 +426,23 @@ _____________________________________________________________________
|
|||||||
Description: "release candidate version",
|
Description: "release candidate version",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.18.5",
|
KubeVersion: "v1.18.5",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.18.5": 1,
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.18.5": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.3-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.18.5",
|
KubeadmVersion: "v1.18.5",
|
||||||
DNSVersion: "1.6.7",
|
DNSVersion: "1.6.7",
|
||||||
EtcdVersion: "3.4.3-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.19.0-rc.1",
|
KubeVersion: "v1.19.0-rc.1",
|
||||||
@ -388,18 +454,18 @@ _____________________________________________________________________
|
|||||||
},
|
},
|
||||||
versionStates: versionStates,
|
versionStates: versionStates,
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.18.5 v1.19.0-rc.1
|
kubelet node1 v1.18.5 v1.19.0-rc.1
|
||||||
|
|
||||||
Upgrade to the latest release candidate version:
|
Upgrade to the latest release candidate version:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.18.5 v1.19.0-rc.1
|
kube-apiserver node1 v1.18.5 v1.19.0-rc.1
|
||||||
kube-controller-manager v1.18.5 v1.19.0-rc.1
|
kube-controller-manager node1 v1.18.5 v1.19.0-rc.1
|
||||||
kube-scheduler v1.18.5 v1.19.0-rc.1
|
kube-scheduler node1 v1.18.5 v1.19.0-rc.1
|
||||||
kube-proxy v1.18.5 v1.19.0-rc.1
|
kube-proxy v1.18.5 v1.19.0-rc.1
|
||||||
CoreDNS 1.6.7 1.7.0
|
CoreDNS 1.6.7 1.7.0
|
||||||
etcd 3.4.3-0 3.4.7-0
|
etcd node1 3.4.3-0 3.4.7-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -429,13 +495,24 @@ _____________________________________________________________________
|
|||||||
Description: "version in the v1.19 series",
|
Description: "version in the v1.19 series",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.19.2",
|
KubeVersion: "v1.19.2",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.19.2": 1,
|
"v1.19.2": {"node1"},
|
||||||
"v1.19.3": 2,
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.19.2": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.19.2": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.19.2": {"node1"},
|
||||||
|
"v1.19.3": {"node2", "node3"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.4.7-0": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.19.2",
|
KubeadmVersion: "v1.19.2",
|
||||||
DNSVersion: "1.7.0",
|
DNSVersion: "1.7.0",
|
||||||
EtcdVersion: "3.4.7-0",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.19.3",
|
KubeVersion: "v1.19.3",
|
||||||
@ -447,78 +524,20 @@ _____________________________________________________________________
|
|||||||
},
|
},
|
||||||
versionStates: versionStates,
|
versionStates: versionStates,
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.19.2 v1.19.3
|
kubelet node1 v1.19.2 v1.19.3
|
||||||
2 x v1.19.3 v1.19.3
|
kubelet node2 v1.19.3 v1.19.3
|
||||||
|
kubelet node3 v1.19.3 v1.19.3
|
||||||
|
|
||||||
Upgrade to the latest version in the v1.19 series:
|
Upgrade to the latest version in the v1.19 series:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.19.2 v1.19.3
|
kube-apiserver node1 v1.19.2 v1.19.3
|
||||||
kube-controller-manager v1.19.2 v1.19.3
|
kube-controller-manager node1 v1.19.2 v1.19.3
|
||||||
kube-scheduler v1.19.2 v1.19.3
|
kube-scheduler node1 v1.19.2 v1.19.3
|
||||||
kube-proxy v1.19.2 v1.19.3
|
|
||||||
CoreDNS 1.7.0 1.7.0
|
|
||||||
etcd 3.4.7-0 3.4.7-0
|
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
|
||||||
|
|
||||||
kubeadm upgrade apply v1.19.3
|
|
||||||
|
|
||||||
Note: Before you can perform this upgrade, you have to update kubeadm to v1.19.3.
|
|
||||||
|
|
||||||
_____________________________________________________________________
|
|
||||||
|
|
||||||
|
|
||||||
The table below shows the current state of component configs as understood by this version of kubeadm.
|
|
||||||
Configs that have a "yes" mark in the "MANUAL UPGRADE REQUIRED" column require manual config upgrade or
|
|
||||||
resetting to kubeadm defaults before a successful upgrade can be performed. The version to manually
|
|
||||||
upgrade to is denoted in the "PREFERRED VERSION" column.
|
|
||||||
|
|
||||||
API GROUP CURRENT VERSION PREFERRED VERSION MANUAL UPGRADE REQUIRED
|
|
||||||
kubeproxy.config.k8s.io v1alpha1 v1alpha1 no
|
|
||||||
kubelet.config.k8s.io v1beta1 v1beta1 no
|
|
||||||
_____________________________________________________________________
|
|
||||||
|
|
||||||
`),
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "external etcd upgrade available",
|
|
||||||
upgrades: []upgrade.Upgrade{
|
|
||||||
{
|
|
||||||
Description: "version in the v1.19 series",
|
|
||||||
Before: upgrade.ClusterState{
|
|
||||||
KubeVersion: "v1.19.2",
|
|
||||||
KubeletVersions: map[string]uint16{
|
|
||||||
"v1.19.2": 1,
|
|
||||||
},
|
|
||||||
KubeadmVersion: "v1.19.2",
|
|
||||||
DNSVersion: "1.7.0",
|
|
||||||
EtcdVersion: "3.4.7-0",
|
|
||||||
},
|
|
||||||
After: upgrade.ClusterState{
|
|
||||||
KubeVersion: "v1.19.3",
|
|
||||||
KubeadmVersion: "v1.19.3",
|
|
||||||
DNSVersion: "1.7.0",
|
|
||||||
EtcdVersion: "3.4.7-0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
versionStates: versionStates,
|
|
||||||
externalEtcd: true,
|
|
||||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
|
||||||
COMPONENT CURRENT TARGET
|
|
||||||
kubelet 1 x v1.19.2 v1.19.3
|
|
||||||
|
|
||||||
Upgrade to the latest version in the v1.19 series:
|
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
|
||||||
kube-apiserver v1.19.2 v1.19.3
|
|
||||||
kube-controller-manager v1.19.2 v1.19.3
|
|
||||||
kube-scheduler v1.19.2 v1.19.3
|
|
||||||
kube-proxy v1.19.2 v1.19.3
|
kube-proxy v1.19.2 v1.19.3
|
||||||
CoreDNS 1.7.0 1.7.0
|
CoreDNS 1.7.0 1.7.0
|
||||||
|
etcd node1 3.4.7-0 3.4.7-0
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -551,7 +570,7 @@ _____________________________________________________________________
|
|||||||
t.Errorf("failed ToPrinter, err: %+v", err)
|
t.Errorf("failed ToPrinter, err: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
plan := genUpgradePlan(rt.upgrades, rt.versionStates, rt.externalEtcd)
|
plan := genUpgradePlan(rt.upgrades, rt.versionStates)
|
||||||
if err := printer.PrintObj(plan, rt.buf); err != nil {
|
if err := printer.PrintObj(plan, rt.buf); err != nil {
|
||||||
t.Errorf("unexpected error when print object: %v", err)
|
t.Errorf("unexpected error when print object: %v", err)
|
||||||
}
|
}
|
||||||
@ -559,7 +578,7 @@ _____________________________________________________________________
|
|||||||
actualBytes := rt.buf.Bytes()
|
actualBytes := rt.buf.Bytes()
|
||||||
if !bytes.Equal(actualBytes, rt.expectedBytes) {
|
if !bytes.Equal(actualBytes, rt.expectedBytes) {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed PrintUpgradePlan:\n\texpected: %q\n\n\tactual : %q",
|
"failed PrintUpgradePlan:\n\texpected: %s\n\n\tactual: %s",
|
||||||
string(rt.expectedBytes),
|
string(rt.expectedBytes),
|
||||||
string(actualBytes),
|
string(actualBytes),
|
||||||
)
|
)
|
||||||
@ -574,12 +593,23 @@ func TestPrintUpgradePlanStructured(t *testing.T) {
|
|||||||
Description: "version in the v1.8 series",
|
Description: "version in the v1.8 series",
|
||||||
Before: upgrade.ClusterState{
|
Before: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.8.1",
|
KubeVersion: "v1.8.1",
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
"v1.8.1": 1,
|
"v1.8.1": {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
"v1.8.1": {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
"v1.8.1": {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
"v1.8.1": {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{
|
||||||
|
"3.0.17": {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: "v1.8.2",
|
KubeadmVersion: "v1.8.2",
|
||||||
DNSVersion: "1.14.5",
|
DNSVersion: "1.14.5",
|
||||||
EtcdVersion: "3.0.17",
|
|
||||||
},
|
},
|
||||||
After: upgrade.ClusterState{
|
After: upgrade.ClusterState{
|
||||||
KubeVersion: "v1.8.3",
|
KubeVersion: "v1.8.3",
|
||||||
@ -624,23 +654,27 @@ func TestPrintUpgradePlanStructured(t *testing.T) {
|
|||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"name": "kubelet",
|
"name": "kubelet",
|
||||||
"currentVersion": "1 x v1.8.1",
|
"currentVersion": "v1.8.1",
|
||||||
"newVersion": "v1.8.3"
|
"newVersion": "v1.8.3",
|
||||||
|
"nodeName": "node1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kube-apiserver",
|
"name": "kube-apiserver",
|
||||||
"currentVersion": "v1.8.1",
|
"currentVersion": "v1.8.1",
|
||||||
"newVersion": "v1.8.3"
|
"newVersion": "v1.8.3",
|
||||||
|
"nodeName": "node1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kube-controller-manager",
|
"name": "kube-controller-manager",
|
||||||
"currentVersion": "v1.8.1",
|
"currentVersion": "v1.8.1",
|
||||||
"newVersion": "v1.8.3"
|
"newVersion": "v1.8.3",
|
||||||
|
"nodeName": "node1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kube-scheduler",
|
"name": "kube-scheduler",
|
||||||
"currentVersion": "v1.8.1",
|
"currentVersion": "v1.8.1",
|
||||||
"newVersion": "v1.8.3"
|
"newVersion": "v1.8.3",
|
||||||
|
"nodeName": "node1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kube-proxy",
|
"name": "kube-proxy",
|
||||||
@ -660,7 +694,8 @@ func TestPrintUpgradePlanStructured(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"name": "etcd",
|
"name": "etcd",
|
||||||
"currentVersion": "3.0.17",
|
"currentVersion": "3.0.17",
|
||||||
"newVersion": "3.0.17"
|
"newVersion": "3.0.17",
|
||||||
|
"nodeName": "node1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -688,18 +723,22 @@ func TestPrintUpgradePlanStructured(t *testing.T) {
|
|||||||
expected: `apiVersion: output.kubeadm.k8s.io/v1alpha3
|
expected: `apiVersion: output.kubeadm.k8s.io/v1alpha3
|
||||||
availableUpgrades:
|
availableUpgrades:
|
||||||
- components:
|
- components:
|
||||||
- currentVersion: 1 x v1.8.1
|
- currentVersion: v1.8.1
|
||||||
name: kubelet
|
name: kubelet
|
||||||
newVersion: v1.8.3
|
newVersion: v1.8.3
|
||||||
|
nodeName: node1
|
||||||
- currentVersion: v1.8.1
|
- currentVersion: v1.8.1
|
||||||
name: kube-apiserver
|
name: kube-apiserver
|
||||||
newVersion: v1.8.3
|
newVersion: v1.8.3
|
||||||
|
nodeName: node1
|
||||||
- currentVersion: v1.8.1
|
- currentVersion: v1.8.1
|
||||||
name: kube-controller-manager
|
name: kube-controller-manager
|
||||||
newVersion: v1.8.3
|
newVersion: v1.8.3
|
||||||
|
nodeName: node1
|
||||||
- currentVersion: v1.8.1
|
- currentVersion: v1.8.1
|
||||||
name: kube-scheduler
|
name: kube-scheduler
|
||||||
newVersion: v1.8.3
|
newVersion: v1.8.3
|
||||||
|
nodeName: node1
|
||||||
- currentVersion: v1.8.1
|
- currentVersion: v1.8.1
|
||||||
name: kube-proxy
|
name: kube-proxy
|
||||||
newVersion: v1.8.3
|
newVersion: v1.8.3
|
||||||
@ -712,6 +751,7 @@ availableUpgrades:
|
|||||||
- currentVersion: 3.0.17
|
- currentVersion: 3.0.17
|
||||||
name: etcd
|
name: etcd
|
||||||
newVersion: 3.0.17
|
newVersion: 3.0.17
|
||||||
|
nodeName: node1
|
||||||
description: version in the v1.8 series
|
description: version in the v1.8 series
|
||||||
configVersions:
|
configVersions:
|
||||||
- currentVersion: v1alpha1
|
- currentVersion: v1alpha1
|
||||||
@ -729,18 +769,18 @@ kind: UpgradePlan
|
|||||||
name: "Text output",
|
name: "Text output",
|
||||||
outputFormat: "text",
|
outputFormat: "text",
|
||||||
expected: `Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
expected: `Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kubelet 1 x v1.8.1 v1.8.3
|
kubelet node1 v1.8.1 v1.8.3
|
||||||
|
|
||||||
Upgrade to the latest version in the v1.8 series:
|
Upgrade to the latest version in the v1.8 series:
|
||||||
|
|
||||||
COMPONENT CURRENT TARGET
|
COMPONENT NODE CURRENT TARGET
|
||||||
kube-apiserver v1.8.1 v1.8.3
|
kube-apiserver node1 v1.8.1 v1.8.3
|
||||||
kube-controller-manager v1.8.1 v1.8.3
|
kube-controller-manager node1 v1.8.1 v1.8.3
|
||||||
kube-scheduler v1.8.1 v1.8.3
|
kube-scheduler node1 v1.8.1 v1.8.3
|
||||||
kube-proxy v1.8.1 v1.8.3
|
kube-proxy v1.8.1 v1.8.3
|
||||||
CoreDNS 1.14.5 1.14.5
|
CoreDNS 1.14.5 1.14.5
|
||||||
etcd 3.0.17 3.0.17
|
etcd node1 3.0.17 3.0.17
|
||||||
|
|
||||||
You can now apply the upgrade by executing the following command:
|
You can now apply the upgrade by executing the following command:
|
||||||
|
|
||||||
@ -774,7 +814,7 @@ _____________________________________________________________________
|
|||||||
t.Errorf("failed ToPrinter, err: %+v", err)
|
t.Errorf("failed ToPrinter, err: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
plan := genUpgradePlan(upgrades, versionStates, false)
|
plan := genUpgradePlan(upgrades, versionStates)
|
||||||
if err := printer.PrintObj(plan, rt.buf); err != nil {
|
if err := printer.PrintObj(plan, rt.buf); err != nil {
|
||||||
t.Errorf("unexpected error when print object: %v", err)
|
t.Errorf("unexpected error when print object: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -52,38 +52,55 @@ func (u *Upgrade) CanUpgradeKubelets() bool {
|
|||||||
return !sameVersionFound
|
return !sameVersionFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanUpgradeEtcd returns whether an upgrade of etcd is possible
|
// ClusterState describes the state of certain versions for a cluster during an upgrade
|
||||||
func (u *Upgrade) CanUpgradeEtcd() bool {
|
|
||||||
return u.Before.EtcdVersion != u.After.EtcdVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClusterState describes the state of certain versions for a cluster
|
|
||||||
type ClusterState struct {
|
type ClusterState struct {
|
||||||
// KubeVersion describes the version of the Kubernetes API Server, Controller Manager, Scheduler and Proxy.
|
// KubeVersion describes the version of latest Kubernetes API Server in the cluster.
|
||||||
KubeVersion string
|
KubeVersion string
|
||||||
// DNSVersion describes the version of the DNS add-on.
|
// DNSVersion describes the version of the DNS add-on.
|
||||||
DNSVersion string
|
DNSVersion string
|
||||||
// KubeadmVersion describes the version of the kubeadm CLI
|
// KubeadmVersion describes the version of the kubeadm CLI
|
||||||
KubeadmVersion string
|
KubeadmVersion string
|
||||||
// KubeletVersions is a map with a version number linked to the amount of kubelets running that version in the cluster
|
|
||||||
KubeletVersions map[string]uint16
|
|
||||||
// EtcdVersion represents the version of etcd used in the cluster
|
// EtcdVersion represents the version of etcd used in the cluster
|
||||||
EtcdVersion string
|
EtcdVersion string
|
||||||
|
|
||||||
|
// The following maps describe the versions of the different components in the cluster.
|
||||||
|
// The key is the version string and the value is a list of nodes that have that version.
|
||||||
|
KubeAPIServerVersions map[string][]string
|
||||||
|
KubeControllerManagerVersions map[string][]string
|
||||||
|
KubeSchedulerVersions map[string][]string
|
||||||
|
EtcdVersions map[string][]string
|
||||||
|
KubeletVersions map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAvailableUpgrades fetches all versions from the specified VersionGetter and computes which
|
// GetAvailableUpgrades fetches all versions from the specified VersionGetter and computes which
|
||||||
// kinds of upgrades can be performed
|
// kinds of upgrades can be performed
|
||||||
func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed, externalEtcd bool, client clientset.Interface, manifestsDir string, printer output.Printer) ([]Upgrade, error) {
|
func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, client clientset.Interface, printer output.Printer) ([]Upgrade, error) {
|
||||||
printer.Printf("[upgrade] Fetching available versions to upgrade to\n")
|
printer.Printf("[upgrade] Fetching available versions to upgrade to\n")
|
||||||
|
|
||||||
// Collect the upgrades kubeadm can do in this list
|
// Collect the upgrades kubeadm can do in this list
|
||||||
var upgrades []Upgrade
|
var upgrades []Upgrade
|
||||||
|
|
||||||
// Get the cluster version
|
// Get the kube-apiserver versions in the cluster
|
||||||
clusterVersionStr, clusterVersion, err := versionGetterImpl.ClusterVersion()
|
kubeAPIServerVersions, err := versionGetterImpl.ComponentVersions(kubeadmconstants.KubeAPIServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return upgrades, err
|
return upgrades, err
|
||||||
}
|
}
|
||||||
|
if len(kubeAPIServerVersions) > 1 {
|
||||||
|
verMsg := []string{}
|
||||||
|
for version, nodes := range kubeAPIServerVersions {
|
||||||
|
verMsg = append(verMsg, fmt.Sprintf("%s on nodes %v", version, nodes))
|
||||||
|
}
|
||||||
|
klog.Warningf("Different API server versions in the cluster were discovered: %v. Please upgrade your control plane"+
|
||||||
|
" nodes to the same version of Kubernetes", strings.Join(verMsg, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the lastest cluster version
|
||||||
|
clusterVersion, err := getLatestClusterVersion(kubeAPIServerVersions)
|
||||||
|
if err != nil {
|
||||||
|
return upgrades, err
|
||||||
|
}
|
||||||
|
clusterVersionStr := clusterVersion.String()
|
||||||
|
|
||||||
printer.Printf("[upgrade/versions] Cluster version: %s\n", clusterVersionStr)
|
printer.Printf("[upgrade/versions] Cluster version: %s\n", clusterVersionStr)
|
||||||
|
|
||||||
// Get current kubeadm CLI version
|
// Get current kubeadm CLI version
|
||||||
@ -109,15 +126,25 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
|
|||||||
return upgrades, err
|
return upgrades, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current stacked etcd version on the local node
|
// Get the kube-controller-manager versions in the cluster
|
||||||
var etcdVersion string
|
kubeControllerManagerVersions, err := versionGetterImpl.ComponentVersions(kubeadmconstants.KubeControllerManager)
|
||||||
if !externalEtcd {
|
|
||||||
etcdVersion, err = GetEtcdImageTagFromStaticPod(manifestsDir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return upgrades, err
|
return upgrades, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the kube-scheduler versions in the cluster
|
||||||
|
kubeSchedulerVersions, err := versionGetterImpl.ComponentVersions(kubeadmconstants.KubeScheduler)
|
||||||
|
if err != nil {
|
||||||
|
return upgrades, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the etcd versions in the cluster
|
||||||
|
etcdVersions, err := versionGetterImpl.ComponentVersions(kubeadmconstants.Etcd)
|
||||||
|
if err != nil {
|
||||||
|
return upgrades, err
|
||||||
|
}
|
||||||
|
isExternalEtcd := len(etcdVersions) == 0
|
||||||
|
|
||||||
dnsVersion, err := dns.DeployedDNSAddon(client)
|
dnsVersion, err := dns.DeployedDNSAddon(client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -128,8 +155,11 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
|
|||||||
KubeVersion: clusterVersionStr,
|
KubeVersion: clusterVersionStr,
|
||||||
DNSVersion: dnsVersion,
|
DNSVersion: dnsVersion,
|
||||||
KubeadmVersion: kubeadmVersionStr,
|
KubeadmVersion: kubeadmVersionStr,
|
||||||
|
KubeAPIServerVersions: kubeAPIServerVersions,
|
||||||
|
KubeControllerManagerVersions: kubeControllerManagerVersions,
|
||||||
|
KubeSchedulerVersions: kubeSchedulerVersions,
|
||||||
KubeletVersions: kubeletVersions,
|
KubeletVersions: kubeletVersions,
|
||||||
EtcdVersion: etcdVersion,
|
EtcdVersions: etcdVersions,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a "dumb guess" that a new minor upgrade is available just because the latest stable version is higher than the cluster version
|
// Do a "dumb guess" that a new minor upgrade is available just because the latest stable version is higher than the cluster version
|
||||||
@ -173,8 +203,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
|
|||||||
KubeVersion: patchVersionStr,
|
KubeVersion: patchVersionStr,
|
||||||
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
||||||
KubeadmVersion: newKubeadmVer,
|
KubeadmVersion: newKubeadmVer,
|
||||||
EtcdVersion: getSuggestedEtcdVersion(externalEtcd, patchVersionStr),
|
EtcdVersion: getSuggestedEtcdVersion(isExternalEtcd, patchVersionStr),
|
||||||
// KubeletVersions is unset here as it is not used anywhere in .After
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -189,8 +218,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
|
|||||||
KubeVersion: stableVersionStr,
|
KubeVersion: stableVersionStr,
|
||||||
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
||||||
KubeadmVersion: stableVersionStr,
|
KubeadmVersion: stableVersionStr,
|
||||||
EtcdVersion: getSuggestedEtcdVersion(externalEtcd, stableVersionStr),
|
EtcdVersion: getSuggestedEtcdVersion(isExternalEtcd, stableVersionStr),
|
||||||
// KubeletVersions is unset here as it is not used anywhere in .After
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -236,8 +264,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
|
|||||||
KubeVersion: previousBranchLatestVersionStr,
|
KubeVersion: previousBranchLatestVersionStr,
|
||||||
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
||||||
KubeadmVersion: previousBranchLatestVersionStr,
|
KubeadmVersion: previousBranchLatestVersionStr,
|
||||||
EtcdVersion: getSuggestedEtcdVersion(externalEtcd, previousBranchLatestVersionStr),
|
EtcdVersion: getSuggestedEtcdVersion(isExternalEtcd, previousBranchLatestVersionStr),
|
||||||
// KubeletVersions is unset here as it is not used anywhere in .After
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -260,8 +287,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
|
|||||||
KubeVersion: unstableKubeVersion,
|
KubeVersion: unstableKubeVersion,
|
||||||
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
DNSVersion: kubeadmconstants.CoreDNSVersion,
|
||||||
KubeadmVersion: unstableKubeVersion,
|
KubeadmVersion: unstableKubeVersion,
|
||||||
EtcdVersion: getSuggestedEtcdVersion(externalEtcd, unstableKubeVersion),
|
EtcdVersion: getSuggestedEtcdVersion(isExternalEtcd, unstableKubeVersion),
|
||||||
// KubeletVersions is unset here as it is not used anywhere in .After
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -294,8 +320,8 @@ func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *versionut
|
|||||||
return patchVersion.LessThan(stableVersion)
|
return patchVersion.LessThan(stableVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSuggestedEtcdVersion(externalEtcd bool, kubernetesVersion string) string {
|
func getSuggestedEtcdVersion(isExternalEtcd bool, kubernetesVersion string) string {
|
||||||
if externalEtcd {
|
if isExternalEtcd {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
etcdVersion, warning, err := kubeadmconstants.EtcdSupportedVersion(kubeadmconstants.SupportedEtcdVersion, kubernetesVersion)
|
etcdVersion, warning, err := kubeadmconstants.EtcdSupportedVersion(kubeadmconstants.SupportedEtcdVersion, kubernetesVersion)
|
||||||
@ -308,3 +334,18 @@ func getSuggestedEtcdVersion(externalEtcd bool, kubernetesVersion string) string
|
|||||||
}
|
}
|
||||||
return etcdVersion.String()
|
return etcdVersion.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLatestClusterVersion(kubeAPIServerVersions map[string][]string) (*versionutil.Version, error) {
|
||||||
|
var latestVersion *versionutil.Version
|
||||||
|
for versionStr, nodes := range kubeAPIServerVersions {
|
||||||
|
ver, err := versionutil.ParseSemantic(versionStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't parse kube-apiserver version %s from nodes %v", versionStr, nodes)
|
||||||
|
}
|
||||||
|
if latestVersion == nil || ver.AtLeast(latestVersion) {
|
||||||
|
latestVersion = ver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return latestVersion, nil
|
||||||
|
}
|
||||||
|
@ -18,11 +18,10 @@ package upgrade
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
apps "k8s.io/api/apps/v1"
|
apps "k8s.io/api/apps/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@ -34,7 +33,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type fakeVersionGetter struct {
|
type fakeVersionGetter struct {
|
||||||
clusterVersion, kubeadmVersion, stableVersion, latestVersion, latestDevBranchVersion, stablePatchVersion, kubeletVersion string
|
clusterVersion string
|
||||||
|
kubeadmVersion string
|
||||||
|
stableVersion string
|
||||||
|
latestVersion string
|
||||||
|
latestDevBranchVersion string
|
||||||
|
stablePatchVersion string
|
||||||
|
kubeletVersion string
|
||||||
|
componentVersion string
|
||||||
|
etcdVersion string
|
||||||
|
isExternalEtcd bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ VersionGetter = &fakeVersionGetter{}
|
var _ VersionGetter = &fakeVersionGetter{}
|
||||||
@ -63,26 +71,30 @@ func (f *fakeVersionGetter) VersionFromCILabel(ciVersionLabel, _ string) (string
|
|||||||
return f.stablePatchVersion, versionutil.MustParseSemantic(f.stablePatchVersion), nil
|
return f.stablePatchVersion, versionutil.MustParseSemantic(f.stablePatchVersion), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// KubeletVersions gets the versions of the kubelets in the cluster
|
// KubeletVersions should return a map with a version and a list of node names that describes how many kubelets there are for that version
|
||||||
func (f *fakeVersionGetter) KubeletVersions() (map[string]uint16, error) {
|
func (f *fakeVersionGetter) KubeletVersions() (map[string][]string, error) {
|
||||||
return map[string]uint16{
|
return map[string][]string{
|
||||||
f.kubeletVersion: 1,
|
f.kubeletVersion: {"node1"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComponentVersions should return a map with a version and a list of node names that describes how many a given control-plane components there are for that version
|
||||||
|
func (f *fakeVersionGetter) ComponentVersions(name string) (map[string][]string, error) {
|
||||||
|
if name == constants.Etcd {
|
||||||
|
if f.isExternalEtcd {
|
||||||
|
return map[string][]string{}, nil
|
||||||
|
}
|
||||||
|
return map[string][]string{
|
||||||
|
f.etcdVersion: {"node1"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string][]string{
|
||||||
|
f.componentVersion: {"node1"},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const fakeCurrentEtcdVersion = "3.1.12"
|
const fakeCurrentEtcdVersion = "3.1.12"
|
||||||
const etcdStaticPod = `apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
component: etcd
|
|
||||||
tier: control-plane
|
|
||||||
name: etcd
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: etcd
|
|
||||||
image: registry.k8s.io/etcd:` + fakeCurrentEtcdVersion
|
|
||||||
|
|
||||||
func getEtcdVersion(v *versionutil.Version) string {
|
func getEtcdVersion(v *versionutil.Version) string {
|
||||||
etcdVer, _, _ := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, v.String())
|
etcdVer, _, _ := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, v.String())
|
||||||
@ -123,15 +135,16 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
expectedUpgrades []Upgrade
|
expectedUpgrades []Upgrade
|
||||||
allowExperimental, allowRCs bool
|
allowExperimental, allowRCs bool
|
||||||
errExpected bool
|
errExpected bool
|
||||||
externalEtcd bool
|
|
||||||
beforeDNSVersion string
|
beforeDNSVersion string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no action needed, already up-to-date",
|
name: "no action needed, already up-to-date",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Y0.String(),
|
clusterVersion: v1Y0.String(),
|
||||||
|
componentVersion: v1Y0.String(),
|
||||||
kubeletVersion: v1Y0.String(),
|
kubeletVersion: v1Y0.String(),
|
||||||
kubeadmVersion: v1Y0.String(),
|
kubeadmVersion: v1Y0.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y0.String(),
|
stablePatchVersion: v1Y0.String(),
|
||||||
stableVersion: v1Y0.String(),
|
stableVersion: v1Y0.String(),
|
||||||
@ -145,8 +158,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "simple patch version upgrade",
|
name: "simple patch version upgrade",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Y1.String(),
|
clusterVersion: v1Y1.String(),
|
||||||
|
componentVersion: v1Y1.String(),
|
||||||
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
||||||
kubeadmVersion: v1Y2.String(),
|
kubeadmVersion: v1Y2.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y3.String(),
|
stablePatchVersion: v1Y3.String(),
|
||||||
stableVersion: v1Y3.String(),
|
stableVersion: v1Y3.String(),
|
||||||
@ -157,12 +172,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y1.String(),
|
KubeVersion: v1Y1.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y1.String(): 1,
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y2.String(),
|
KubeadmVersion: v1Y2.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Y3.String(),
|
KubeVersion: v1Y3.String(),
|
||||||
@ -179,25 +203,35 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "simple patch version upgrade with external etcd",
|
name: "simple patch version upgrade with external etcd",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Y1.String(),
|
clusterVersion: v1Y1.String(),
|
||||||
|
componentVersion: v1Y1.String(),
|
||||||
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
||||||
kubeadmVersion: v1Y2.String(),
|
kubeadmVersion: v1Y2.String(),
|
||||||
|
isExternalEtcd: true,
|
||||||
|
|
||||||
stablePatchVersion: v1Y3.String(),
|
stablePatchVersion: v1Y3.String(),
|
||||||
stableVersion: v1Y3.String(),
|
stableVersion: v1Y3.String(),
|
||||||
},
|
},
|
||||||
beforeDNSVersion: fakeCurrentCoreDNSVersion,
|
beforeDNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
externalEtcd: true,
|
|
||||||
expectedUpgrades: []Upgrade{
|
expectedUpgrades: []Upgrade{
|
||||||
{
|
{
|
||||||
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y1.String(),
|
KubeVersion: v1Y1.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y1.String(): 1,
|
v1Y1.String(): {"node1"},
|
||||||
},
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
EtcdVersions: map[string][]string{},
|
||||||
KubeadmVersion: v1Y2.String(),
|
KubeadmVersion: v1Y2.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: "",
|
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Y3.String(),
|
KubeVersion: v1Y3.String(),
|
||||||
@ -214,8 +248,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "no version provided to offline version getter does not change behavior",
|
name: "no version provided to offline version getter does not change behavior",
|
||||||
vg: NewOfflineVersionGetter(&fakeVersionGetter{
|
vg: NewOfflineVersionGetter(&fakeVersionGetter{
|
||||||
clusterVersion: v1Y1.String(),
|
clusterVersion: v1Y1.String(),
|
||||||
|
componentVersion: v1Y1.String(),
|
||||||
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
||||||
kubeadmVersion: v1Y2.String(),
|
kubeadmVersion: v1Y2.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y3.String(),
|
stablePatchVersion: v1Y3.String(),
|
||||||
stableVersion: v1Y3.String(),
|
stableVersion: v1Y3.String(),
|
||||||
@ -226,12 +262,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y1.String(),
|
KubeVersion: v1Y1.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y1.String(): 1,
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y2.String(),
|
KubeadmVersion: v1Y2.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Y3.String(),
|
KubeVersion: v1Y3.String(),
|
||||||
@ -248,8 +293,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "minor version upgrade only",
|
name: "minor version upgrade only",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Y1.String(),
|
clusterVersion: v1Y1.String(),
|
||||||
|
componentVersion: v1Y1.String(),
|
||||||
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
kubeletVersion: v1Y1.String(), // the kubelet are on the same version as the control plane
|
||||||
kubeadmVersion: v1Z0.String(),
|
kubeadmVersion: v1Z0.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y1.String(),
|
stablePatchVersion: v1Y1.String(),
|
||||||
stableVersion: v1Z0.String(),
|
stableVersion: v1Z0.String(),
|
||||||
@ -260,12 +307,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "stable version",
|
Description: "stable version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y1.String(),
|
KubeVersion: v1Y1.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y1.String(): 1,
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Z0.String(),
|
KubeadmVersion: v1Z0.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0.String(),
|
KubeVersion: v1Z0.String(),
|
||||||
@ -282,8 +338,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "both minor version upgrade and patch version upgrade available",
|
name: "both minor version upgrade and patch version upgrade available",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Y3.String(),
|
clusterVersion: v1Y3.String(),
|
||||||
|
componentVersion: v1Y3.String(),
|
||||||
kubeletVersion: v1Y3.String(), // the kubelet are on the same version as the control plane
|
kubeletVersion: v1Y3.String(), // the kubelet are on the same version as the control plane
|
||||||
kubeadmVersion: v1Y5.String(),
|
kubeadmVersion: v1Y5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y5.String(),
|
stablePatchVersion: v1Y5.String(),
|
||||||
stableVersion: v1Z1.String(),
|
stableVersion: v1Z1.String(),
|
||||||
@ -294,12 +352,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y3.String(),
|
KubeVersion: v1Y3.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y3.String(): 1,
|
v1Y3.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y3.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y3.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y3.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y5.String(),
|
KubeadmVersion: v1Y5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Y5.String(),
|
KubeVersion: v1Y5.String(),
|
||||||
@ -312,12 +379,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "stable version",
|
Description: "stable version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y3.String(),
|
KubeVersion: v1Y3.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y3.String(): 1,
|
v1Y3.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y3.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y3.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y3.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y5.String(),
|
KubeadmVersion: v1Y5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z1.String(),
|
KubeVersion: v1Z1.String(),
|
||||||
@ -334,8 +410,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "allow experimental upgrades, but no upgrade available",
|
name: "allow experimental upgrades, but no upgrade available",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Z0alpha2.String(),
|
clusterVersion: v1Z0alpha2.String(),
|
||||||
|
componentVersion: v1Z0alpha2.String(),
|
||||||
kubeletVersion: v1Y5.String(),
|
kubeletVersion: v1Y5.String(),
|
||||||
kubeadmVersion: v1Y5.String(),
|
kubeadmVersion: v1Y5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y5.String(),
|
stablePatchVersion: v1Y5.String(),
|
||||||
stableVersion: v1Y5.String(),
|
stableVersion: v1Y5.String(),
|
||||||
@ -350,8 +428,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "upgrade to an unstable version should be supported",
|
name: "upgrade to an unstable version should be supported",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Y5.String(),
|
clusterVersion: v1Y5.String(),
|
||||||
|
componentVersion: v1Y5.String(),
|
||||||
kubeletVersion: v1Y5.String(),
|
kubeletVersion: v1Y5.String(),
|
||||||
kubeadmVersion: v1Y5.String(),
|
kubeadmVersion: v1Y5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y5.String(),
|
stablePatchVersion: v1Y5.String(),
|
||||||
stableVersion: v1Y5.String(),
|
stableVersion: v1Y5.String(),
|
||||||
@ -363,12 +443,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "experimental version",
|
Description: "experimental version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y5.String(),
|
KubeVersion: v1Y5.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y5.String(): 1,
|
v1Y5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y5.String(),
|
KubeadmVersion: v1Y5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0alpha2.String(),
|
KubeVersion: v1Z0alpha2.String(),
|
||||||
@ -385,8 +474,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "upgrade from an unstable version to an unstable version should be supported",
|
name: "upgrade from an unstable version to an unstable version should be supported",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1Z0alpha1.String(),
|
clusterVersion: v1Z0alpha1.String(),
|
||||||
|
componentVersion: v1Z0alpha1.String(),
|
||||||
kubeletVersion: v1Y5.String(),
|
kubeletVersion: v1Y5.String(),
|
||||||
kubeadmVersion: v1Y5.String(),
|
kubeadmVersion: v1Y5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1Y5.String(),
|
stablePatchVersion: v1Y5.String(),
|
||||||
stableVersion: v1Y5.String(),
|
stableVersion: v1Y5.String(),
|
||||||
@ -398,12 +489,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "experimental version",
|
Description: "experimental version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Z0alpha1.String(),
|
KubeVersion: v1Z0alpha1.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y5.String(): 1,
|
v1Z0alpha1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Z0alpha1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Z0alpha1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y5.String(),
|
KubeadmVersion: v1Y5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0alpha2.String(),
|
KubeVersion: v1Z0alpha2.String(),
|
||||||
@ -420,8 +520,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "v1.X.0-alpha.0 should be ignored",
|
name: "v1.X.0-alpha.0 should be ignored",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1X5.String(),
|
clusterVersion: v1X5.String(),
|
||||||
|
componentVersion: v1X5.String(),
|
||||||
kubeletVersion: v1X5.String(),
|
kubeletVersion: v1X5.String(),
|
||||||
kubeadmVersion: v1X5.String(),
|
kubeadmVersion: v1X5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1X5.String(),
|
stablePatchVersion: v1X5.String(),
|
||||||
stableVersion: v1X5.String(),
|
stableVersion: v1X5.String(),
|
||||||
@ -434,12 +536,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "experimental version",
|
Description: "experimental version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1X5.String(),
|
KubeVersion: v1X5.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1X5.String(): 1,
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1X5.String(),
|
KubeadmVersion: v1X5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0beta1.String(),
|
KubeVersion: v1Z0beta1.String(),
|
||||||
@ -456,8 +567,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "upgrade to an RC version should be supported",
|
name: "upgrade to an RC version should be supported",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1X5.String(),
|
clusterVersion: v1X5.String(),
|
||||||
|
componentVersion: v1X5.String(),
|
||||||
kubeletVersion: v1X5.String(),
|
kubeletVersion: v1X5.String(),
|
||||||
kubeadmVersion: v1X5.String(),
|
kubeadmVersion: v1X5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1X5.String(),
|
stablePatchVersion: v1X5.String(),
|
||||||
stableVersion: v1X5.String(),
|
stableVersion: v1X5.String(),
|
||||||
@ -470,12 +583,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "release candidate version",
|
Description: "release candidate version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1X5.String(),
|
KubeVersion: v1X5.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1X5.String(): 1,
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1X5.String(),
|
KubeadmVersion: v1X5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0rc1.String(),
|
KubeVersion: v1Z0rc1.String(),
|
||||||
@ -492,8 +614,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "it is possible (but very uncommon) that the latest version from the previous branch is an rc and the current latest version is alpha.0. In that case, show the RC",
|
name: "it is possible (but very uncommon) that the latest version from the previous branch is an rc and the current latest version is alpha.0. In that case, show the RC",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1X5.String(),
|
clusterVersion: v1X5.String(),
|
||||||
|
componentVersion: v1X5.String(),
|
||||||
kubeletVersion: v1X5.String(),
|
kubeletVersion: v1X5.String(),
|
||||||
kubeadmVersion: v1X5.String(),
|
kubeadmVersion: v1X5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1X5.String(),
|
stablePatchVersion: v1X5.String(),
|
||||||
stableVersion: v1X5.String(),
|
stableVersion: v1X5.String(),
|
||||||
@ -506,12 +630,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "experimental version", // Note that this is considered an experimental version in this uncommon scenario
|
Description: "experimental version", // Note that this is considered an experimental version in this uncommon scenario
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1X5.String(),
|
KubeVersion: v1X5.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1X5.String(): 1,
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1X5.String(),
|
KubeadmVersion: v1X5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0rc1.String(),
|
KubeVersion: v1Z0rc1.String(),
|
||||||
@ -528,8 +661,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "upgrade to an RC version should be supported. There may also be an even newer unstable version.",
|
name: "upgrade to an RC version should be supported. There may also be an even newer unstable version.",
|
||||||
vg: &fakeVersionGetter{
|
vg: &fakeVersionGetter{
|
||||||
clusterVersion: v1X5.String(),
|
clusterVersion: v1X5.String(),
|
||||||
|
componentVersion: v1X5.String(),
|
||||||
kubeletVersion: v1X5.String(),
|
kubeletVersion: v1X5.String(),
|
||||||
kubeadmVersion: v1X5.String(),
|
kubeadmVersion: v1X5.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
|
|
||||||
stablePatchVersion: v1X5.String(),
|
stablePatchVersion: v1X5.String(),
|
||||||
stableVersion: v1X5.String(),
|
stableVersion: v1X5.String(),
|
||||||
@ -542,12 +677,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "release candidate version",
|
Description: "release candidate version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1X5.String(),
|
KubeVersion: v1X5.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1X5.String(): 1,
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1X5.String(),
|
KubeadmVersion: v1X5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z0rc1.String(),
|
KubeVersion: v1Z0rc1.String(),
|
||||||
@ -560,12 +704,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: "experimental version",
|
Description: "experimental version",
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1X5.String(),
|
KubeVersion: v1X5.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1X5.String(): 1,
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1X5.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1X5.String(),
|
KubeadmVersion: v1X5.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Y0alpha1.String(),
|
KubeVersion: v1Y0alpha1.String(),
|
||||||
@ -583,8 +736,10 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
name: "offline version getter",
|
name: "offline version getter",
|
||||||
vg: NewOfflineVersionGetter(&fakeVersionGetter{
|
vg: NewOfflineVersionGetter(&fakeVersionGetter{
|
||||||
clusterVersion: v1Y1.String(),
|
clusterVersion: v1Y1.String(),
|
||||||
|
componentVersion: v1Y1.String(),
|
||||||
kubeletVersion: v1Y0.String(),
|
kubeletVersion: v1Y0.String(),
|
||||||
kubeadmVersion: v1Y1.String(),
|
kubeadmVersion: v1Y1.String(),
|
||||||
|
etcdVersion: fakeCurrentEtcdVersion,
|
||||||
}, v1Z1.String()),
|
}, v1Z1.String()),
|
||||||
beforeDNSVersion: fakeCurrentCoreDNSVersion,
|
beforeDNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
expectedUpgrades: []Upgrade{
|
expectedUpgrades: []Upgrade{
|
||||||
@ -592,12 +747,21 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
Description: fmt.Sprintf("version in the v%d.%d series", v1Y0.Major(), v1Y0.Minor()),
|
||||||
Before: ClusterState{
|
Before: ClusterState{
|
||||||
KubeVersion: v1Y1.String(),
|
KubeVersion: v1Y1.String(),
|
||||||
KubeletVersions: map[string]uint16{
|
KubeAPIServerVersions: map[string][]string{
|
||||||
v1Y0.String(): 1,
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeControllerManagerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeSchedulerVersions: map[string][]string{
|
||||||
|
v1Y1.String(): {"node1"},
|
||||||
|
},
|
||||||
|
KubeletVersions: map[string][]string{
|
||||||
|
v1Y0.String(): {"node1"},
|
||||||
},
|
},
|
||||||
KubeadmVersion: v1Y1.String(),
|
KubeadmVersion: v1Y1.String(),
|
||||||
DNSVersion: fakeCurrentCoreDNSVersion,
|
DNSVersion: fakeCurrentCoreDNSVersion,
|
||||||
EtcdVersion: fakeCurrentEtcdVersion,
|
EtcdVersions: map[string][]string{fakeCurrentEtcdVersion: {"node1"}},
|
||||||
},
|
},
|
||||||
After: ClusterState{
|
After: ClusterState{
|
||||||
KubeVersion: v1Z1.String(),
|
KubeVersion: v1Z1.String(),
|
||||||
@ -642,27 +806,18 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
manifestsDir, err := os.MkdirTemp("", "GetAvailableUpgrades-test-manifests")
|
actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, client, &output.TextPrinter{})
|
||||||
if err != nil {
|
if diff := cmp.Diff(rt.expectedUpgrades, actualUpgrades); len(diff) > 0 {
|
||||||
t.Fatalf("Unable to create temporary directory: %v", err)
|
t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades:\n%v\n\tgot:\n%v\n\tdiff:\n%v", rt.expectedUpgrades, actualUpgrades, diff)
|
||||||
}
|
|
||||||
defer os.RemoveAll(manifestsDir)
|
|
||||||
|
|
||||||
if err = os.WriteFile(constants.GetStaticPodFilepath(constants.Etcd, manifestsDir), []byte(etcdStaticPod), 0644); err != nil {
|
|
||||||
t.Fatalf("Unable to create test static pod manifest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, rt.externalEtcd, client, manifestsDir, &output.TextPrinter{})
|
|
||||||
if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) {
|
|
||||||
t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades)
|
|
||||||
}
|
}
|
||||||
if rt.errExpected && actualErr == nil {
|
if rt.errExpected && actualErr == nil {
|
||||||
t.Error("unexpected success")
|
t.Error("unexpected success")
|
||||||
} else if !rt.errExpected && actualErr != nil {
|
} else if !rt.errExpected && actualErr != nil {
|
||||||
t.Errorf("unexpected failure: %v", actualErr)
|
t.Errorf("unexpected failure: %v", actualErr)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) {
|
if diff := cmp.Diff(rt.expectedUpgrades, actualUpgrades); len(diff) > 0 {
|
||||||
t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades)
|
t.Logf("diff: %s", cmp.Diff(rt.expectedUpgrades, actualUpgrades))
|
||||||
|
t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades:\n%v\n\tgot:\n%v\n\tdiff:\n%v", rt.expectedUpgrades, actualUpgrades, diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -671,46 +826,46 @@ func TestGetAvailableUpgrades(t *testing.T) {
|
|||||||
func TestKubeletUpgrade(t *testing.T) {
|
func TestKubeletUpgrade(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
before map[string]uint16
|
before map[string][]string
|
||||||
after string
|
after string
|
||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "upgrade from v1.10.1 to v1.10.3 is available",
|
name: "upgrade from v1.10.1 to v1.10.3 is available",
|
||||||
before: map[string]uint16{
|
before: map[string][]string{
|
||||||
"v1.10.1": 1,
|
"v1.10.1": {"node1"},
|
||||||
},
|
},
|
||||||
after: "v1.10.3",
|
after: "v1.10.3",
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "upgrade from v1.10.1 and v1.10.3/100 to v1.10.3 is available",
|
name: "upgrade from v1.10.1 and v1.10.3/2 to v1.10.3 is available",
|
||||||
before: map[string]uint16{
|
before: map[string][]string{
|
||||||
"v1.10.1": 1,
|
"v1.10.1": {"node1"},
|
||||||
"v1.10.3": 100,
|
"v1.10.3": {"node2", "node3"},
|
||||||
},
|
},
|
||||||
after: "v1.10.3",
|
after: "v1.10.3",
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "upgrade from v1.10.3 to v1.10.3 is not available",
|
name: "upgrade from v1.10.3 to v1.10.3 is not available",
|
||||||
before: map[string]uint16{
|
before: map[string][]string{
|
||||||
"v1.10.3": 1,
|
"v1.10.3": {"node1"},
|
||||||
},
|
},
|
||||||
after: "v1.10.3",
|
after: "v1.10.3",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "upgrade from v1.10.3/100 to v1.10.3 is not available",
|
name: "upgrade from v1.10.3/2 to v1.10.3 is not available",
|
||||||
before: map[string]uint16{
|
before: map[string][]string{
|
||||||
"v1.10.3": 100,
|
"v1.10.3": {"node1", "node2"},
|
||||||
},
|
},
|
||||||
after: "v1.10.3",
|
after: "v1.10.3",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "upgrade is not available if we don't know anything about the earlier state",
|
name: "upgrade is not available if we don't know anything about the earlier state",
|
||||||
before: map[string]uint16{},
|
before: map[string][]string{},
|
||||||
after: "v1.10.3",
|
after: "v1.10.3",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
@ -168,7 +168,7 @@ func detectUnstableVersionError(newK8sVersion *version.Version, newK8sVersionStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// detectTooOldKubelets errors out if the kubelet versions are so old that an unsupported skew would happen if the cluster was upgraded
|
// detectTooOldKubelets errors out if the kubelet versions are so old that an unsupported skew would happen if the cluster was upgraded
|
||||||
func detectTooOldKubelets(newK8sVersion *version.Version, kubeletVersions map[string]uint16) error {
|
func detectTooOldKubelets(newK8sVersion *version.Version, kubeletVersions map[string][]string) error {
|
||||||
var tooOldKubeletVersions []string
|
var tooOldKubeletVersions []string
|
||||||
for versionStr := range kubeletVersions {
|
for versionStr := range kubeletVersions {
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@ package upgrade
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
versionutil "k8s.io/apimachinery/pkg/util/version"
|
versionutil "k8s.io/apimachinery/pkg/util/version"
|
||||||
pkgversion "k8s.io/apimachinery/pkg/version"
|
pkgversion "k8s.io/apimachinery/pkg/version"
|
||||||
@ -29,7 +29,9 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/component-base/version"
|
"k8s.io/component-base/version"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/image"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VersionGetter defines an interface for fetching different versions.
|
// VersionGetter defines an interface for fetching different versions.
|
||||||
@ -41,8 +43,10 @@ type VersionGetter interface {
|
|||||||
KubeadmVersion() (string, *versionutil.Version, error)
|
KubeadmVersion() (string, *versionutil.Version, error)
|
||||||
// VersionFromCILabel should resolve CI labels like `latest`, `stable`, `stable-1.8`, etc. to real versions
|
// VersionFromCILabel should resolve CI labels like `latest`, `stable`, `stable-1.8`, etc. to real versions
|
||||||
VersionFromCILabel(string, string) (string, *versionutil.Version, error)
|
VersionFromCILabel(string, string) (string, *versionutil.Version, error)
|
||||||
// KubeletVersions should return a map with a version and a number that describes how many kubelets there are for that version
|
// KubeletVersions should return a map with a version and a list of node names that describes how many kubelets there are for that version
|
||||||
KubeletVersions() (map[string]uint16, error)
|
KubeletVersions() (map[string][]string, error)
|
||||||
|
// ComponentVersions should return a map with a version and a list of node names that describes how many a given control-plane components there are for that version
|
||||||
|
ComponentVersions(string) (map[string][]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KubeVersionGetter handles the version-fetching mechanism from external sources
|
// KubeVersionGetter handles the version-fetching mechanism from external sources
|
||||||
@ -111,27 +115,42 @@ func (g *KubeVersionGetter) VersionFromCILabel(ciVersionLabel, description strin
|
|||||||
return versionStr, ver, nil
|
return versionStr, ver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// KubeletVersions gets the versions of the kubelets in the cluster
|
// KubeletVersions gets the versions of the kubelets in the cluster.
|
||||||
func (g *KubeVersionGetter) KubeletVersions() (map[string]uint16, error) {
|
func (g *KubeVersionGetter) KubeletVersions() (map[string][]string, error) {
|
||||||
nodes, err := g.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
|
nodes, err := g.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("couldn't list all nodes in cluster")
|
return nil, errors.New("couldn't list all nodes in cluster")
|
||||||
}
|
}
|
||||||
return computeKubeletVersions(nodes.Items), nil
|
|
||||||
|
// map kubelet version to a list of node names
|
||||||
|
kubeletVersions := make(map[string][]string)
|
||||||
|
for _, node := range nodes.Items {
|
||||||
|
kver := node.Status.NodeInfo.KubeletVersion
|
||||||
|
kubeletVersions[kver] = append(kubeletVersions[kver], node.Name)
|
||||||
|
}
|
||||||
|
return kubeletVersions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// computeKubeletVersions returns a string-int map that describes how many nodes are of a specific version
|
// ComponentVersions gets the versions of the control-plane components in the cluster.
|
||||||
func computeKubeletVersions(nodes []v1.Node) map[string]uint16 {
|
// The name parameter is the name of the component to get the versions for.
|
||||||
kubeletVersions := make(map[string]uint16)
|
// The function returns a map with the version as the key and a list of node names as the value.
|
||||||
for _, node := range nodes {
|
func (g *KubeVersionGetter) ComponentVersions(name string) (map[string][]string, error) {
|
||||||
kver := node.Status.NodeInfo.KubeletVersion
|
podList, err := g.client.CoreV1().Pods(metav1.NamespaceSystem).List(
|
||||||
if _, found := kubeletVersions[kver]; !found {
|
context.TODO(),
|
||||||
kubeletVersions[kver] = 1
|
metav1.ListOptions{
|
||||||
continue
|
LabelSelector: fmt.Sprintf("component=%s,tier=%s", name, constants.ControlPlaneTier),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "couldn't list pods in cluster")
|
||||||
}
|
}
|
||||||
kubeletVersions[kver]++
|
|
||||||
|
componentVersions := make(map[string][]string)
|
||||||
|
for _, pod := range podList.Items {
|
||||||
|
tag := convertImageTagMetadataToSemver(image.TagFromImage(pod.Spec.Containers[0].Image))
|
||||||
|
componentVersions[tag] = append(componentVersions[tag], pod.Spec.NodeName)
|
||||||
}
|
}
|
||||||
return kubeletVersions
|
return componentVersions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OfflineVersionGetter will use the version provided or
|
// OfflineVersionGetter will use the version provided or
|
||||||
|
@ -148,7 +148,7 @@ func TestKubeVersionGetterKubeletVersions(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
nodes *v1.NodeList
|
nodes *v1.NodeList
|
||||||
want map[string]uint16
|
want map[string][]string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -181,9 +181,9 @@ func TestKubeVersionGetterKubeletVersions(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: map[string]uint16{
|
want: map[string][]string{
|
||||||
"v1.28.0": 1,
|
"v1.28.0": {"node1"},
|
||||||
"v1.28.1": 2,
|
"v1.28.1": {"node2", "node3"},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@ -201,15 +201,15 @@ func TestKubeVersionGetterKubeletVersions(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: map[string]uint16{
|
want: map[string][]string{
|
||||||
"": 2,
|
"": {"node2", "node3"},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "node list is empty",
|
name: "node list is empty",
|
||||||
nodes: &v1.NodeList{},
|
nodes: &v1.NodeList{},
|
||||||
want: map[string]uint16{},
|
want: map[string][]string{},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user