in the new output API output.kubeadm.k8s.io/v1alpha3 modify the UpgradePlan structure to include a list of multiple available upgrades.
This commit is contained in:
		@@ -33,6 +33,7 @@ import (
 | 
				
			|||||||
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
 | 
					func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
 | 
				
			||||||
	return []interface{}{
 | 
						return []interface{}{
 | 
				
			||||||
		fuzzBootstrapToken,
 | 
							fuzzBootstrapToken,
 | 
				
			||||||
 | 
							fuzzUpgradePlan,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,3 +46,10 @@ func fuzzBootstrapToken(obj *output.BootstrapToken, c fuzz.Continue) {
 | 
				
			|||||||
	obj.Usages = []string{"authentication", "signing"}
 | 
						obj.Usages = []string{"authentication", "signing"}
 | 
				
			||||||
	obj.Groups = []string{constants.NodeBootstrapTokenAuthGroup}
 | 
						obj.Groups = []string{constants.NodeBootstrapTokenAuthGroup}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Remove this func when v1alpha2 is removed
 | 
				
			||||||
 | 
					func fuzzUpgradePlan(obj *output.UpgradePlan, c fuzz.Continue) {
 | 
				
			||||||
 | 
						// Pin the value to avoid round tripping the AvailableUpgrades field
 | 
				
			||||||
 | 
						// which is not present in the v1alpha2 version.
 | 
				
			||||||
 | 
						obj.AvailableUpgrades = nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,14 +73,28 @@ type ComponentConfigVersionState struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AvailableUpgrade represents information for a single available upgrade.
 | 
				
			||||||
 | 
					type AvailableUpgrade struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Description string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Components []ComponentUpgradePlan
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpgradePlan represents information about upgrade plan for the output
 | 
					// UpgradePlan represents information about upgrade plan for the output
 | 
				
			||||||
// produced by 'kubeadm upgrade plan'
 | 
					// produced by 'kubeadm upgrade plan'
 | 
				
			||||||
type UpgradePlan struct {
 | 
					type UpgradePlan struct {
 | 
				
			||||||
	metav1.TypeMeta
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Components []ComponentUpgradePlan
 | 
						AvailableUpgrades []AvailableUpgrade
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ConfigVersions []ComponentConfigVersionState
 | 
						ConfigVersions []ComponentConfigVersionState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Remove this field when v1alpha2 is removed
 | 
				
			||||||
 | 
						Components []ComponentUpgradePlan
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Certificate represents information for a certificate or a certificate authority when using the check-expiration command.
 | 
					// Certificate represents information for a certificate or a certificate authority when using the check-expiration command.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								cmd/kubeadm/app/apis/output/v1alpha2/conversion.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmd/kubeadm/app/apis/output/v1alpha2/conversion.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2024 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package v1alpha2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/conversion"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_output_UpgradePlan_To_v1alpha2_UpgradePlan converts a private UpgradePlan to public UpgradePlan.
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -81,7 +81,7 @@ func RegisterConversions(s *runtime.Scheme) error {
 | 
				
			|||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := s.AddGeneratedConversionFunc((*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 {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -191,12 +191,8 @@ 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 {
 | 
				
			||||||
	out.Components = *(*[]ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
						// 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))
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Convert_output_UpgradePlan_To_v1alpha2_UpgradePlan is an autogenerated conversion function.
 | 
					 | 
				
			||||||
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)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/conversion.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmd/kubeadm/app/apis/output/v1alpha3/conversion.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2024 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package v1alpha3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/conversion"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan converts a private UpgradePlan to public UpgradePlan.
 | 
				
			||||||
 | 
					func Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -27,4 +27,6 @@ limitations under the License.
 | 
				
			|||||||
// Changes since v1alpha2:
 | 
					// Changes since v1alpha2:
 | 
				
			||||||
//   - Added support for outputting certificate expiration information for "kubeadm certs check-expiration"
 | 
					//   - Added support for outputting certificate expiration information for "kubeadm certs check-expiration"
 | 
				
			||||||
//     with the CertificateExpirationInfo structure.
 | 
					//     with the CertificateExpirationInfo structure.
 | 
				
			||||||
 | 
					//   - Introduce a (breaking) change to the UpgradePlan structure used by "kubeadm upgrade plan".
 | 
				
			||||||
 | 
					//     UpgradePlan now contains a list of AvailableUpgrade structures.
 | 
				
			||||||
package v1alpha3 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
					package v1alpha3 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,14 +73,25 @@ type ComponentConfigVersionState struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AvailableUpgrade represents information for a single available upgrade.
 | 
				
			||||||
 | 
					type AvailableUpgrade struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Description string `json:"description"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Components []ComponentUpgradePlan `json:"components"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpgradePlan represents information about upgrade plan for the output
 | 
					// UpgradePlan represents information about upgrade plan for the output
 | 
				
			||||||
// produced by 'kubeadm upgrade plan'
 | 
					// produced by 'kubeadm upgrade plan'
 | 
				
			||||||
type UpgradePlan struct {
 | 
					type UpgradePlan struct {
 | 
				
			||||||
	metav1.TypeMeta
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Components []ComponentUpgradePlan `json:"components"`
 | 
						AvailableUpgrades []AvailableUpgrade `json:"availableUpgrades,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ConfigVersions []ComponentConfigVersionState `json:"configVersions"`
 | 
						ConfigVersions []ComponentConfigVersionState `json:"configVersions,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Certificate represents information for a certificate or a certificate authority when using the check-expiration command.
 | 
					// Certificate represents information for a certificate or a certificate authority when using the check-expiration command.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,16 @@ func init() {
 | 
				
			|||||||
// RegisterConversions adds conversion functions to the given scheme.
 | 
					// RegisterConversions adds conversion functions to the given scheme.
 | 
				
			||||||
// Public to allow building arbitrary schemes.
 | 
					// Public to allow building arbitrary schemes.
 | 
				
			||||||
func RegisterConversions(s *runtime.Scheme) error {
 | 
					func RegisterConversions(s *runtime.Scheme) error {
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*AvailableUpgrade)(nil), (*output.AvailableUpgrade)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_v1alpha3_AvailableUpgrade_To_output_AvailableUpgrade(a.(*AvailableUpgrade), b.(*output.AvailableUpgrade), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*output.AvailableUpgrade)(nil), (*AvailableUpgrade)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_output_AvailableUpgrade_To_v1alpha3_AvailableUpgrade(a.(*output.AvailableUpgrade), b.(*AvailableUpgrade), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*output.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
						if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*output.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
		return Convert_v1alpha3_BootstrapToken_To_output_BootstrapToken(a.(*BootstrapToken), b.(*output.BootstrapToken), scope)
 | 
							return Convert_v1alpha3_BootstrapToken_To_output_BootstrapToken(a.(*BootstrapToken), b.(*output.BootstrapToken), scope)
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
@@ -101,7 +111,7 @@ func RegisterConversions(s *runtime.Scheme) error {
 | 
				
			|||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := s.AddGeneratedConversionFunc((*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_v1alpha3_UpgradePlan(a.(*output.UpgradePlan), b.(*UpgradePlan), scope)
 | 
							return Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan(a.(*output.UpgradePlan), b.(*UpgradePlan), scope)
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -109,6 +119,28 @@ func RegisterConversions(s *runtime.Scheme) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_v1alpha3_AvailableUpgrade_To_output_AvailableUpgrade(in *AvailableUpgrade, out *output.AvailableUpgrade, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Description = in.Description
 | 
				
			||||||
 | 
						out.Components = *(*[]output.ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_v1alpha3_AvailableUpgrade_To_output_AvailableUpgrade is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_v1alpha3_AvailableUpgrade_To_output_AvailableUpgrade(in *AvailableUpgrade, out *output.AvailableUpgrade, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_v1alpha3_AvailableUpgrade_To_output_AvailableUpgrade(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_output_AvailableUpgrade_To_v1alpha3_AvailableUpgrade(in *output.AvailableUpgrade, out *AvailableUpgrade, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Description = in.Description
 | 
				
			||||||
 | 
						out.Components = *(*[]ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_output_AvailableUpgrade_To_v1alpha3_AvailableUpgrade is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_output_AvailableUpgrade_To_v1alpha3_AvailableUpgrade(in *output.AvailableUpgrade, out *AvailableUpgrade, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_output_AvailableUpgrade_To_v1alpha3_AvailableUpgrade(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func autoConvert_v1alpha3_BootstrapToken_To_output_BootstrapToken(in *BootstrapToken, out *output.BootstrapToken, s conversion.Scope) error {
 | 
					func autoConvert_v1alpha3_BootstrapToken_To_output_BootstrapToken(in *BootstrapToken, out *output.BootstrapToken, s conversion.Scope) error {
 | 
				
			||||||
	out.BootstrapToken = in.BootstrapToken
 | 
						out.BootstrapToken = in.BootstrapToken
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -252,7 +284,7 @@ func Convert_output_Images_To_v1alpha3_Images(in *output.Images, out *Images, s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func autoConvert_v1alpha3_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *output.UpgradePlan, s conversion.Scope) error {
 | 
					func autoConvert_v1alpha3_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *output.UpgradePlan, s conversion.Scope) error {
 | 
				
			||||||
	out.Components = *(*[]output.ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
						out.AvailableUpgrades = *(*[]output.AvailableUpgrade)(unsafe.Pointer(&in.AvailableUpgrades))
 | 
				
			||||||
	out.ConfigVersions = *(*[]output.ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
 | 
						out.ConfigVersions = *(*[]output.ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -263,12 +295,8 @@ func Convert_v1alpha3_UpgradePlan_To_output_UpgradePlan(in *UpgradePlan, out *ou
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func autoConvert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
 | 
					func autoConvert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
 | 
				
			||||||
	out.Components = *(*[]ComponentUpgradePlan)(unsafe.Pointer(&in.Components))
 | 
						out.AvailableUpgrades = *(*[]AvailableUpgrade)(unsafe.Pointer(&in.AvailableUpgrades))
 | 
				
			||||||
	out.ConfigVersions = *(*[]ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
 | 
						out.ConfigVersions = *(*[]ComponentConfigVersionState)(unsafe.Pointer(&in.ConfigVersions))
 | 
				
			||||||
 | 
						// WARNING: in.Components requires manual conversion: does not exist in peer-type
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan is an autogenerated conversion function.
 | 
					 | 
				
			||||||
func Convert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in *output.UpgradePlan, out *UpgradePlan, s conversion.Scope) error {
 | 
					 | 
				
			||||||
	return autoConvert_output_UpgradePlan_To_v1alpha3_UpgradePlan(in, out, s)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,36 @@ import (
 | 
				
			|||||||
	runtime "k8s.io/apimachinery/pkg/runtime"
 | 
						runtime "k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *AvailableUpgrade) DeepCopyInto(out *AvailableUpgrade) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						out.TypeMeta = in.TypeMeta
 | 
				
			||||||
 | 
						if in.Components != nil {
 | 
				
			||||||
 | 
							in, out := &in.Components, &out.Components
 | 
				
			||||||
 | 
							*out = make([]ComponentUpgradePlan, len(*in))
 | 
				
			||||||
 | 
							copy(*out, *in)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AvailableUpgrade.
 | 
				
			||||||
 | 
					func (in *AvailableUpgrade) DeepCopy() *AvailableUpgrade {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(AvailableUpgrade)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
				
			||||||
 | 
					func (in *AvailableUpgrade) DeepCopyObject() runtime.Object {
 | 
				
			||||||
 | 
						if c := in.DeepCopy(); c != nil {
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
 | 
					func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
 | 
				
			||||||
	*out = *in
 | 
						*out = *in
 | 
				
			||||||
@@ -182,10 +212,12 @@ func (in *Images) DeepCopyObject() runtime.Object {
 | 
				
			|||||||
func (in *UpgradePlan) DeepCopyInto(out *UpgradePlan) {
 | 
					func (in *UpgradePlan) DeepCopyInto(out *UpgradePlan) {
 | 
				
			||||||
	*out = *in
 | 
						*out = *in
 | 
				
			||||||
	out.TypeMeta = in.TypeMeta
 | 
						out.TypeMeta = in.TypeMeta
 | 
				
			||||||
	if in.Components != nil {
 | 
						if in.AvailableUpgrades != nil {
 | 
				
			||||||
		in, out := &in.Components, &out.Components
 | 
							in, out := &in.AvailableUpgrades, &out.AvailableUpgrades
 | 
				
			||||||
		*out = make([]ComponentUpgradePlan, len(*in))
 | 
							*out = make([]AvailableUpgrade, len(*in))
 | 
				
			||||||
		copy(*out, *in)
 | 
							for i := range *in {
 | 
				
			||||||
 | 
								(*in)[i].DeepCopyInto(&(*out)[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if in.ConfigVersions != nil {
 | 
						if in.ConfigVersions != nil {
 | 
				
			||||||
		in, out := &in.ConfigVersions, &out.ConfigVersions
 | 
							in, out := &in.ConfigVersions, &out.ConfigVersions
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								cmd/kubeadm/app/apis/output/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										45
									
								
								cmd/kubeadm/app/apis/output/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							@@ -25,6 +25,36 @@ import (
 | 
				
			|||||||
	runtime "k8s.io/apimachinery/pkg/runtime"
 | 
						runtime "k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *AvailableUpgrade) DeepCopyInto(out *AvailableUpgrade) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						out.TypeMeta = in.TypeMeta
 | 
				
			||||||
 | 
						if in.Components != nil {
 | 
				
			||||||
 | 
							in, out := &in.Components, &out.Components
 | 
				
			||||||
 | 
							*out = make([]ComponentUpgradePlan, len(*in))
 | 
				
			||||||
 | 
							copy(*out, *in)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AvailableUpgrade.
 | 
				
			||||||
 | 
					func (in *AvailableUpgrade) DeepCopy() *AvailableUpgrade {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(AvailableUpgrade)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
				
			||||||
 | 
					func (in *AvailableUpgrade) DeepCopyObject() runtime.Object {
 | 
				
			||||||
 | 
						if c := in.DeepCopy(); c != nil {
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
 | 
					func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
 | 
				
			||||||
	*out = *in
 | 
						*out = *in
 | 
				
			||||||
@@ -182,16 +212,23 @@ func (in *Images) DeepCopyObject() runtime.Object {
 | 
				
			|||||||
func (in *UpgradePlan) DeepCopyInto(out *UpgradePlan) {
 | 
					func (in *UpgradePlan) DeepCopyInto(out *UpgradePlan) {
 | 
				
			||||||
	*out = *in
 | 
						*out = *in
 | 
				
			||||||
	out.TypeMeta = in.TypeMeta
 | 
						out.TypeMeta = in.TypeMeta
 | 
				
			||||||
	if in.Components != nil {
 | 
						if in.AvailableUpgrades != nil {
 | 
				
			||||||
		in, out := &in.Components, &out.Components
 | 
							in, out := &in.AvailableUpgrades, &out.AvailableUpgrades
 | 
				
			||||||
		*out = make([]ComponentUpgradePlan, len(*in))
 | 
							*out = make([]AvailableUpgrade, len(*in))
 | 
				
			||||||
		copy(*out, *in)
 | 
							for i := range *in {
 | 
				
			||||||
 | 
								(*in)[i].DeepCopyInto(&(*out)[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if in.ConfigVersions != nil {
 | 
						if in.ConfigVersions != nil {
 | 
				
			||||||
		in, out := &in.ConfigVersions, &out.ConfigVersions
 | 
							in, out := &in.ConfigVersions, &out.ConfigVersions
 | 
				
			||||||
		*out = make([]ComponentConfigVersionState, len(*in))
 | 
							*out = make([]ComponentConfigVersionState, len(*in))
 | 
				
			||||||
		copy(*out, *in)
 | 
							copy(*out, *in)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if in.Components != nil {
 | 
				
			||||||
 | 
							in, out := &in.Components, &out.Components
 | 
				
			||||||
 | 
							*out = make([]ComponentUpgradePlan, len(*in))
 | 
				
			||||||
 | 
							copy(*out, *in)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,11 +31,10 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/version"
 | 
						"k8s.io/apimachinery/pkg/util/version"
 | 
				
			||||||
	"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
						"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
				
			||||||
	"k8s.io/cli-runtime/pkg/printers"
 | 
					 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
 | 
						outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
 | 
				
			||||||
	outputapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha2"
 | 
						outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
				
			||||||
	cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
 | 
						cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
				
			||||||
@@ -59,7 +58,7 @@ func newCmdPlan(apf *applyPlanFlags) *cobra.Command {
 | 
				
			|||||||
		applyPlanFlags: apf,
 | 
							applyPlanFlags: apf,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	outputFlags := newUpgradePlanPrintFlags(output.TextOutput)
 | 
						outputFlags := output.NewOutputFlags(&upgradePlanTextPrintFlags{}).WithTypeSetter(outputapischeme.Scheme).WithDefaultOutput(output.TextOutput)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:   "plan [version] [flags]",
 | 
							Use:   "plan [version] [flags]",
 | 
				
			||||||
@@ -82,174 +81,15 @@ func newCmdPlan(apf *applyPlanFlags) *cobra.Command {
 | 
				
			|||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// newComponentUpgradePlan helper creates outputapiv1alpha2.ComponentUpgradePlan object
 | 
					// newComponentUpgradePlan helper creates outputapiv1alpha3.ComponentUpgradePlan object
 | 
				
			||||||
func newComponentUpgradePlan(name, currentVersion, newVersion string) outputapiv1alpha2.ComponentUpgradePlan {
 | 
					func newComponentUpgradePlan(name, currentVersion, newVersion string) outputapiv1alpha3.ComponentUpgradePlan {
 | 
				
			||||||
	return outputapiv1alpha2.ComponentUpgradePlan{
 | 
						return outputapiv1alpha3.ComponentUpgradePlan{
 | 
				
			||||||
		Name:           name,
 | 
							Name:           name,
 | 
				
			||||||
		CurrentVersion: currentVersion,
 | 
							CurrentVersion: currentVersion,
 | 
				
			||||||
		NewVersion:     newVersion,
 | 
							NewVersion:     newVersion,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// upgradePlanPrintFlags defines a printer flag structure for the
 | 
					 | 
				
			||||||
// upgrade plan kubeadm command and provides a method
 | 
					 | 
				
			||||||
// of retrieving a known printer based on flag values provided.
 | 
					 | 
				
			||||||
type upgradePlanPrintFlags struct {
 | 
					 | 
				
			||||||
	// JSONYamlPrintFlags provides default flags necessary for json/yaml printing
 | 
					 | 
				
			||||||
	JSONYamlPrintFlags *upgradePlanJSONYamlPrintFlags
 | 
					 | 
				
			||||||
	// TextPrintFlags provides default flags necessary for text printing
 | 
					 | 
				
			||||||
	TextPrintFlags *upgradePlanTextPrintFlags
 | 
					 | 
				
			||||||
	// TypeSetterPrinter is an implementation of ResourcePrinter that wraps another printer with types set on the objects
 | 
					 | 
				
			||||||
	TypeSetterPrinter *printers.TypeSetterPrinter
 | 
					 | 
				
			||||||
	// OutputFormat contains currently set output format
 | 
					 | 
				
			||||||
	OutputFormat string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newUpgradePlanPrintFlags(outputFormat string) *upgradePlanPrintFlags {
 | 
					 | 
				
			||||||
	return &upgradePlanPrintFlags{
 | 
					 | 
				
			||||||
		JSONYamlPrintFlags: &upgradePlanJSONYamlPrintFlags{},
 | 
					 | 
				
			||||||
		TextPrintFlags:     &upgradePlanTextPrintFlags{},
 | 
					 | 
				
			||||||
		TypeSetterPrinter:  printers.NewTypeSetter(outputapischeme.Scheme),
 | 
					 | 
				
			||||||
		OutputFormat:       strings.ToLower(outputFormat),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AllowedFormats returns a list of allowed output formats
 | 
					 | 
				
			||||||
func (pf *upgradePlanPrintFlags) AllowedFormats() []string {
 | 
					 | 
				
			||||||
	ret := pf.TextPrintFlags.AllowedFormats()
 | 
					 | 
				
			||||||
	return append(ret, pf.JSONYamlPrintFlags.AllowedFormats()...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AddFlags receives a *cobra.Command reference and binds
 | 
					 | 
				
			||||||
// flags related to Kubeadm printing to it
 | 
					 | 
				
			||||||
func (pf *upgradePlanPrintFlags) AddFlags(cmd *cobra.Command) {
 | 
					 | 
				
			||||||
	pf.TextPrintFlags.AddFlags(cmd)
 | 
					 | 
				
			||||||
	pf.JSONYamlPrintFlags.AddFlags(cmd)
 | 
					 | 
				
			||||||
	// TODO: once we are confident the feature is graduated we should remove the EXPERIMENTAL text below:
 | 
					 | 
				
			||||||
	// https://github.com/kubernetes/kubeadm/issues/494
 | 
					 | 
				
			||||||
	cmd.Flags().StringVarP(&pf.OutputFormat, "output", "o", pf.OutputFormat, fmt.Sprintf("EXPERIMENTAL: Output format. One of: %s.", strings.Join(pf.AllowedFormats(), "|")))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ToPrinter receives an outputFormat and returns a printer capable of
 | 
					 | 
				
			||||||
// handling format printing.
 | 
					 | 
				
			||||||
// Returns error if the specified outputFormat does not match supported formats.
 | 
					 | 
				
			||||||
func (pf *upgradePlanPrintFlags) ToPrinter() (output.Printer, error) {
 | 
					 | 
				
			||||||
	switch pf.OutputFormat {
 | 
					 | 
				
			||||||
	case output.TextOutput:
 | 
					 | 
				
			||||||
		return pf.TextPrintFlags.ToPrinter(pf.OutputFormat)
 | 
					 | 
				
			||||||
	case output.JSONOutput:
 | 
					 | 
				
			||||||
		return newUpgradePlanJSONYAMLPrinter(pf.TypeSetterPrinter.WrapToPrinter(pf.JSONYamlPrintFlags.ToPrinter(output.JSONOutput)))
 | 
					 | 
				
			||||||
	case output.YAMLOutput:
 | 
					 | 
				
			||||||
		return newUpgradePlanJSONYAMLPrinter(pf.TypeSetterPrinter.WrapToPrinter(pf.JSONYamlPrintFlags.ToPrinter(output.YAMLOutput)))
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &pf.OutputFormat, AllowedFormats: pf.AllowedFormats()}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type upgradePlanJSONYamlPrintFlags struct {
 | 
					 | 
				
			||||||
	genericclioptions.JSONYamlPrintFlags
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AllowedFormats returns a list of allowed output formats
 | 
					 | 
				
			||||||
func (pf *upgradePlanJSONYamlPrintFlags) AllowedFormats() []string {
 | 
					 | 
				
			||||||
	return []string{output.JSONOutput, output.YAMLOutput}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// upgradePlanJSONYAMLPrinter prints upgrade plan in a JSON or YAML format
 | 
					 | 
				
			||||||
type upgradePlanJSONYAMLPrinter struct {
 | 
					 | 
				
			||||||
	output.ResourcePrinterWrapper
 | 
					 | 
				
			||||||
	Components     []outputapiv1alpha2.ComponentUpgradePlan
 | 
					 | 
				
			||||||
	ConfigVersions []outputapiv1alpha2.ComponentConfigVersionState
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// newUpgradePlanJSONYAMLPrinter creates a new upgradePlanJSONYAMLPrinter object
 | 
					 | 
				
			||||||
func newUpgradePlanJSONYAMLPrinter(resourcePrinter printers.ResourcePrinter, err error) (output.Printer, error) {
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &upgradePlanJSONYAMLPrinter{ResourcePrinterWrapper: output.ResourcePrinterWrapper{Printer: resourcePrinter}}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PrintObj is an implementation of ResourcePrinter.PrintObj that adds object to the buffer
 | 
					 | 
				
			||||||
func (p *upgradePlanJSONYAMLPrinter) PrintObj(obj runtime.Object, writer io.Writer) error {
 | 
					 | 
				
			||||||
	item, ok := obj.(*outputapiv1alpha2.ComponentUpgradePlan)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return errors.Errorf("expected ComponentUpgradePlan, but got %+v", obj)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	p.Components = append(p.Components, *item)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Flush writes any buffered data once last object is added
 | 
					 | 
				
			||||||
func (p *upgradePlanJSONYAMLPrinter) Flush(writer io.Writer, last bool) {
 | 
					 | 
				
			||||||
	if !last {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(p.Components) == 0 && len(p.ConfigVersions) == 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	plan := &outputapiv1alpha2.UpgradePlan{Components: p.Components, ConfigVersions: p.ConfigVersions}
 | 
					 | 
				
			||||||
	if err := p.Printer.PrintObj(plan, writer); err != nil {
 | 
					 | 
				
			||||||
		fmt.Fprintf(os.Stderr, "could not flush output buffer: %v\n", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	p.Components = p.Components[:0]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close does nothing.
 | 
					 | 
				
			||||||
func (p *upgradePlanJSONYAMLPrinter) Close(writer io.Writer) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// upgradePlanTextPrinter prints upgrade plan in a text form
 | 
					 | 
				
			||||||
type upgradePlanTextPrinter struct {
 | 
					 | 
				
			||||||
	output.TextPrinter
 | 
					 | 
				
			||||||
	columns   []string
 | 
					 | 
				
			||||||
	tabwriter *tabwriter.Writer
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Flush writes any buffered data
 | 
					 | 
				
			||||||
func (p *upgradePlanTextPrinter) Flush(writer io.Writer, last bool) {
 | 
					 | 
				
			||||||
	if p.tabwriter != nil {
 | 
					 | 
				
			||||||
		p.tabwriter.Flush()
 | 
					 | 
				
			||||||
		p.tabwriter = nil
 | 
					 | 
				
			||||||
		p.Fprintln(writer, "")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PrintObj is an implementation of ResourcePrinter.PrintObj for upgrade plan plain text output
 | 
					 | 
				
			||||||
func (p *upgradePlanTextPrinter) PrintObj(obj runtime.Object, writer io.Writer) error {
 | 
					 | 
				
			||||||
	if p.tabwriter == nil {
 | 
					 | 
				
			||||||
		p.tabwriter = tabwriter.NewWriter(writer, 10, 4, 3, ' ', 0)
 | 
					 | 
				
			||||||
		// Print header
 | 
					 | 
				
			||||||
		fmt.Fprintln(p.tabwriter, strings.Join(p.columns, "\t"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	item, ok := obj.(*outputapiv1alpha2.ComponentUpgradePlan)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return errors.Errorf("expected ComponentUpgradePlan, but got %+v", obj)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Print item
 | 
					 | 
				
			||||||
	fmt.Fprintf(p.tabwriter, "%s\t%s\t%s\n", item.Name, item.CurrentVersion, item.NewVersion)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// upgradePlanTextPrintFlags provides flags necessary for printing upgrade plan in a text form
 | 
					 | 
				
			||||||
type upgradePlanTextPrintFlags struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (pf *upgradePlanTextPrintFlags) AddFlags(cmd *cobra.Command) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AllowedFormats returns a list of allowed output formats
 | 
					 | 
				
			||||||
func (pf *upgradePlanTextPrintFlags) AllowedFormats() []string {
 | 
					 | 
				
			||||||
	return []string{output.TextOutput}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ToPrinter returns a kubeadm printer for the text output format
 | 
					 | 
				
			||||||
func (pf *upgradePlanTextPrintFlags) ToPrinter(outputFormat string) (output.Printer, error) {
 | 
					 | 
				
			||||||
	if outputFormat == output.TextOutput {
 | 
					 | 
				
			||||||
		return &upgradePlanTextPrinter{columns: []string{"COMPONENT", "CURRENT", "TARGET"}}, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: []string{output.JSONOutput, output.YAMLOutput, output.TextOutput}}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// runPlan takes care of outputting available versions to upgrade to for the user
 | 
					// runPlan takes care of outputting available versions to upgrade to for the user
 | 
				
			||||||
func runPlan(flags *planFlags, args []string, printer output.Printer) error {
 | 
					func runPlan(flags *planFlags, args []string, printer output.Printer) error {
 | 
				
			||||||
	// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning.
 | 
						// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning.
 | 
				
			||||||
@@ -284,34 +124,24 @@ func runPlan(flags *planFlags, args []string, printer output.Printer) error {
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// A workaround to set the configVersionStates in the printer
 | 
						// Generate and print the upgrade plan
 | 
				
			||||||
	if p, ok := printer.(*upgradePlanJSONYAMLPrinter); ok {
 | 
						plan := genUpgradePlan(availUpgrades, configVersionStates, isExternalEtcd)
 | 
				
			||||||
		p.ConfigVersions = configVersionStates
 | 
						return printer.PrintObj(plan, os.Stdout)
 | 
				
			||||||
	}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Generate and print upgrade plans
 | 
					// genUpgradePlan generates upgrade plan from available upgrades and component config version states
 | 
				
			||||||
 | 
					func genUpgradePlan(availUpgrades []upgrade.Upgrade, configVersions []outputapiv1alpha3.ComponentConfigVersionState, isExternalEtcd bool) *outputapiv1alpha3.UpgradePlan {
 | 
				
			||||||
 | 
						plan := &outputapiv1alpha3.UpgradePlan{ConfigVersions: configVersions}
 | 
				
			||||||
	for _, up := range availUpgrades {
 | 
						for _, up := range availUpgrades {
 | 
				
			||||||
		plan, unstableVersionFlag, err := genUpgradePlan(&up, isExternalEtcd)
 | 
							au := genAvailableUpgrade(&up, isExternalEtcd)
 | 
				
			||||||
		if err != nil {
 | 
							plan.AvailableUpgrades = append(plan.AvailableUpgrades, au)
 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Actually, this is needed for machine-readable output only.
 | 
					 | 
				
			||||||
		// printUpgradePlan won't output the configVersionStates as it will simply print the same table several times
 | 
					 | 
				
			||||||
		// in the human-readable output if it did so
 | 
					 | 
				
			||||||
		plan.ConfigVersions = configVersionStates
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		printUpgradePlan(&up, plan, unstableVersionFlag, isExternalEtcd, os.Stdout, printer)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return plan
 | 
				
			||||||
	// Finally, print the component config state table
 | 
					 | 
				
			||||||
	printComponentConfigVersionStates(configVersionStates, os.Stdout, printer)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO There is currently no way to cleanly output upgrades that involve adding, removing, or changing components
 | 
					// TODO There is currently no way to cleanly output upgrades that involve adding, removing, or changing components
 | 
				
			||||||
// https://github.com/kubernetes/kubeadm/issues/810 was created to track addressing this.
 | 
					// https://github.com/kubernetes/kubeadm/issues/810 was created to track addressing this.
 | 
				
			||||||
func appendDNSComponent(components []outputapiv1alpha2.ComponentUpgradePlan, up *upgrade.Upgrade, name string) []outputapiv1alpha2.ComponentUpgradePlan {
 | 
					func appendDNSComponent(components []outputapiv1alpha3.ComponentUpgradePlan, up *upgrade.Upgrade, name string) []outputapiv1alpha3.ComponentUpgradePlan {
 | 
				
			||||||
	beforeVersion := up.Before.DNSVersion
 | 
						beforeVersion := up.Before.DNSVersion
 | 
				
			||||||
	afterVersion := up.After.DNSVersion
 | 
						afterVersion := up.After.DNSVersion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -321,23 +151,20 @@ func appendDNSComponent(components []outputapiv1alpha2.ComponentUpgradePlan, up
 | 
				
			|||||||
	return components
 | 
						return components
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// genUpgradePlan generates output-friendly upgrade plan out of upgrade.Upgrade structure
 | 
					// appendKubeadmComponent appends kubeadm component to the list of components
 | 
				
			||||||
func genUpgradePlan(up *upgrade.Upgrade, isExternalEtcd bool) (*outputapiv1alpha2.UpgradePlan, string, error) {
 | 
					func appendKubeadmComponent(components []outputapiv1alpha3.ComponentUpgradePlan, up *upgrade.Upgrade, name string) []outputapiv1alpha3.ComponentUpgradePlan {
 | 
				
			||||||
	newK8sVersion, err := version.ParseSemantic(up.After.KubeVersion)
 | 
						beforeVersion := up.Before.KubeadmVersion
 | 
				
			||||||
	if err != nil {
 | 
						afterVersion := up.After.KubeadmVersion
 | 
				
			||||||
		return nil, "", errors.Wrapf(err, "Unable to parse normalized version %q as a semantic version", up.After.KubeVersion)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unstableVersionFlag := ""
 | 
						if beforeVersion != "" || afterVersion != "" {
 | 
				
			||||||
	if len(newK8sVersion.PreRelease()) != 0 {
 | 
							components = append(components, newComponentUpgradePlan(name, beforeVersion, afterVersion))
 | 
				
			||||||
		if strings.HasPrefix(newK8sVersion.PreRelease(), "rc") {
 | 
					 | 
				
			||||||
			unstableVersionFlag = " --allow-release-candidate-upgrades"
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			unstableVersionFlag = " --allow-experimental-upgrades"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return components
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	components := []outputapiv1alpha2.ComponentUpgradePlan{}
 | 
					// genAvailableUpgrade generates available upgrade from upgrade object and external etcd boolean
 | 
				
			||||||
 | 
					func genAvailableUpgrade(up *upgrade.Upgrade, isExternalEtcd bool) outputapiv1alpha3.AvailableUpgrade {
 | 
				
			||||||
 | 
						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-count>. Here all the keys are put into a slice and sorted
 | 
				
			||||||
@@ -354,59 +181,13 @@ func genUpgradePlan(up *upgrade.Upgrade, isExternalEtcd bool) (*outputapiv1alpha
 | 
				
			|||||||
	components = append(components, newComponentUpgradePlan(constants.KubeProxy, up.Before.KubeVersion, up.After.KubeVersion))
 | 
						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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !isExternalEtcd {
 | 
						if !isExternalEtcd {
 | 
				
			||||||
		components = append(components, newComponentUpgradePlan(constants.Etcd, up.Before.EtcdVersion, up.After.EtcdVersion))
 | 
							components = append(components, newComponentUpgradePlan(constants.Etcd, up.Before.EtcdVersion, up.After.EtcdVersion))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &outputapiv1alpha2.UpgradePlan{Components: components}, unstableVersionFlag, nil
 | 
						return outputapiv1alpha3.AvailableUpgrade{Description: up.Description, Components: components}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// printUpgradePlan prints a UX-friendly overview of what versions are available to upgrade to
 | 
					 | 
				
			||||||
func printUpgradePlan(up *upgrade.Upgrade, plan *outputapiv1alpha2.UpgradePlan, unstableVersionFlag string, isExternalEtcd bool, writer io.Writer, printer output.Printer) {
 | 
					 | 
				
			||||||
	printHeader := true
 | 
					 | 
				
			||||||
	printManualUpgradeHeader := true
 | 
					 | 
				
			||||||
	for _, component := range plan.Components {
 | 
					 | 
				
			||||||
		if isExternalEtcd && component.Name == constants.Etcd {
 | 
					 | 
				
			||||||
			// Don't print etcd if it's external
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		} else if component.Name == constants.Kubelet {
 | 
					 | 
				
			||||||
			if printManualUpgradeHeader {
 | 
					 | 
				
			||||||
				printer.Fprintln(writer, "Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':")
 | 
					 | 
				
			||||||
				plan := newComponentUpgradePlan(component.Name, component.CurrentVersion, component.NewVersion)
 | 
					 | 
				
			||||||
				printer.PrintObj(&plan, writer)
 | 
					 | 
				
			||||||
				printManualUpgradeHeader = false
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				plan := newComponentUpgradePlan("", component.CurrentVersion, component.NewVersion)
 | 
					 | 
				
			||||||
				printer.PrintObj(&plan, writer)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if printHeader {
 | 
					 | 
				
			||||||
				// End of manual upgrades table
 | 
					 | 
				
			||||||
				printer.Flush(writer, false)
 | 
					 | 
				
			||||||
				printer.Fprintf(writer, "Upgrade to the latest %s:\n", up.Description)
 | 
					 | 
				
			||||||
				printer.Fprintln(writer, "")
 | 
					 | 
				
			||||||
				printHeader = false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			plan := newComponentUpgradePlan(component.Name, component.CurrentVersion, component.NewVersion)
 | 
					 | 
				
			||||||
			printer.PrintObj(&plan, writer)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printer.Flush(writer, true)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printer.Fprintln(writer, "You can now apply the upgrade by executing the following command:")
 | 
					 | 
				
			||||||
	printer.Fprintln(writer, "")
 | 
					 | 
				
			||||||
	printer.Fprintf(writer, "\tkubeadm upgrade apply %s%s\n", up.After.KubeVersion, unstableVersionFlag)
 | 
					 | 
				
			||||||
	printer.Fprintln(writer, "")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if up.Before.KubeadmVersion != up.After.KubeadmVersion {
 | 
					 | 
				
			||||||
		printer.Fprintf(writer, "Note: Before you can perform this upgrade, you have to update kubeadm to %s.\n", up.After.KubeadmVersion)
 | 
					 | 
				
			||||||
		printer.Fprintln(writer, "")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printLineSeparator(writer, printer)
 | 
					 | 
				
			||||||
	printer.Close(writer)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
 | 
					// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
 | 
				
			||||||
@@ -419,6 +200,143 @@ func sortedSliceFromStringIntMap(strMap map[string]uint16) []string {
 | 
				
			|||||||
	return strSlice
 | 
						return strSlice
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// upgradePlanTextPrintFlags provides flags necessary for printing upgrade plan in a text form
 | 
				
			||||||
 | 
					type upgradePlanTextPrintFlags struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToPrinter returns a kubeadm printer for the text output format
 | 
				
			||||||
 | 
					func (tpf *upgradePlanTextPrintFlags) ToPrinter(outputFormat string) (output.Printer, error) {
 | 
				
			||||||
 | 
						if outputFormat == output.TextOutput {
 | 
				
			||||||
 | 
							return &upgradePlanTextPrinter{}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: []string{output.TextOutput}}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// upgradePlanTextPrinter prints upgrade plan in a text form
 | 
				
			||||||
 | 
					type upgradePlanTextPrinter struct {
 | 
				
			||||||
 | 
						output.TextPrinter
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrintObj is an implementation of ResourcePrinter.PrintObj for upgrade plan plain text output
 | 
				
			||||||
 | 
					func (printer *upgradePlanTextPrinter) PrintObj(obj runtime.Object, writer io.Writer) error {
 | 
				
			||||||
 | 
						plan, ok := obj.(*outputapiv1alpha3.UpgradePlan)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return errors.Errorf("expected UpgradePlan, but got %+v", obj)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, au := range plan.AvailableUpgrades {
 | 
				
			||||||
 | 
							if err := printer.printAvailableUpgrade(writer, &au); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						printer.printComponentConfigVersionStates(writer, plan.ConfigVersions)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// printUpgradePlan prints a UX-friendly overview of what versions are available to upgrade to
 | 
				
			||||||
 | 
					func (printer *upgradePlanTextPrinter) printAvailableUpgrade(writer io.Writer, au *outputapiv1alpha3.AvailableUpgrade) error {
 | 
				
			||||||
 | 
						var kubeVersion string
 | 
				
			||||||
 | 
						var beforeKubeadmVersion, afterKubeadmVersion string
 | 
				
			||||||
 | 
						for _, component := range au.Components {
 | 
				
			||||||
 | 
							if component.Name == constants.KubeAPIServer {
 | 
				
			||||||
 | 
								kubeVersion = component.NewVersion
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if component.Name == constants.Kubeadm {
 | 
				
			||||||
 | 
								beforeKubeadmVersion = component.CurrentVersion
 | 
				
			||||||
 | 
								afterKubeadmVersion = component.NewVersion
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newK8sVersion, err := version.ParseSemantic(kubeVersion)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errors.Wrapf(err, "Unable to parse normalized version %q as a semantic version", kubeVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unstableVersionFlag := ""
 | 
				
			||||||
 | 
						if len(newK8sVersion.PreRelease()) != 0 {
 | 
				
			||||||
 | 
							if strings.HasPrefix(newK8sVersion.PreRelease(), "rc") {
 | 
				
			||||||
 | 
								unstableVersionFlag = " --allow-release-candidate-upgrades"
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								unstableVersionFlag = " --allow-experimental-upgrades"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _ = 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)
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(tabw, strings.Join([]string{"COMPONENT", "CURRENT", "TARGET"}, "\t"))
 | 
				
			||||||
 | 
						for i, component := range au.Components {
 | 
				
			||||||
 | 
							if component.Name != constants.Kubelet {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if i == 0 {
 | 
				
			||||||
 | 
								_, _ = 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()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(writer, "")
 | 
				
			||||||
 | 
						_, _ = printer.Fprintf(writer, "Upgrade to the latest %s:\n", au.Description)
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(writer, "")
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(tabw, strings.Join([]string{"COMPONENT", "CURRENT", "TARGET"}, "\t"))
 | 
				
			||||||
 | 
						for _, component := range au.Components {
 | 
				
			||||||
 | 
							if component.Name == constants.Kubelet || component.Name == constants.Kubeadm {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, _ = printer.Fprintf(tabw, "%s\t%s\t%s\n", component.Name, component.CurrentVersion, component.NewVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_ = tabw.Flush()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(writer, "")
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(writer, "You can now apply the upgrade by executing the following command:")
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(writer, "")
 | 
				
			||||||
 | 
						_, _ = printer.Fprintf(writer, "\tkubeadm upgrade apply %s%s\n", kubeVersion, unstableVersionFlag)
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(writer, "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if beforeKubeadmVersion != afterKubeadmVersion {
 | 
				
			||||||
 | 
							_, _ = printer.Fprintf(writer, "Note: Before you can perform this upgrade, you have to update kubeadm to %s.\n", afterKubeadmVersion)
 | 
				
			||||||
 | 
							_, _ = printer.Fprintln(writer, "")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printer.printLineSeparator(writer)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// printComponentConfigVersionStates prints a UX-friendly overview of the current state of component configs
 | 
				
			||||||
 | 
					func (printer *upgradePlanTextPrinter) printComponentConfigVersionStates(w io.Writer, versionStates []outputapiv1alpha3.ComponentConfigVersionState) {
 | 
				
			||||||
 | 
						if len(versionStates) == 0 {
 | 
				
			||||||
 | 
							_, _ = printer.Fprintln(w, "No information available on component configs.")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(w, dedent.Dedent(`
 | 
				
			||||||
 | 
							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.
 | 
				
			||||||
 | 
						`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tabw := tabwriter.NewWriter(w, 10, 4, 3, ' ', 0)
 | 
				
			||||||
 | 
						_, _ = printer.Fprintln(tabw, strings.Join([]string{"API GROUP", "CURRENT VERSION", "PREFERRED VERSION", "MANUAL UPGRADE REQUIRED"}, "\t"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, state := range versionStates {
 | 
				
			||||||
 | 
							_, _ = printer.Fprintf(tabw,
 | 
				
			||||||
 | 
								"%s\t%s\t%s\t%s\n",
 | 
				
			||||||
 | 
								state.Group,
 | 
				
			||||||
 | 
								strOrDash(state.CurrentVersion),
 | 
				
			||||||
 | 
								strOrDash(state.PreferredVersion),
 | 
				
			||||||
 | 
								yesOrNo(state.ManualUpgradeRequired),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_ = tabw.Flush()
 | 
				
			||||||
 | 
						printer.printLineSeparator(w)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (printer *upgradePlanTextPrinter) printLineSeparator(w io.Writer) {
 | 
				
			||||||
 | 
						_, _ = printer.Fprintf(w, "_____________________________________________________________________\n\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func strOrDash(s string) string {
 | 
					func strOrDash(s string) string {
 | 
				
			||||||
	if s != "" {
 | 
						if s != "" {
 | 
				
			||||||
		return s
 | 
							return s
 | 
				
			||||||
@@ -432,37 +350,3 @@ func yesOrNo(b bool) string {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return "no"
 | 
						return "no"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func printLineSeparator(w io.Writer, printer output.Printer) {
 | 
					 | 
				
			||||||
	printer.Fprintf(w, "_____________________________________________________________________\n\n")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func printComponentConfigVersionStates(versionStates []outputapiv1alpha2.ComponentConfigVersionState, w io.Writer, printer output.Printer) {
 | 
					 | 
				
			||||||
	if len(versionStates) == 0 {
 | 
					 | 
				
			||||||
		printer.Fprintln(w, "No information available on component configs.")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printer.Fprintln(w, dedent.Dedent(`
 | 
					 | 
				
			||||||
		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.
 | 
					 | 
				
			||||||
	`))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tabw := tabwriter.NewWriter(w, 10, 4, 3, ' ', 0)
 | 
					 | 
				
			||||||
	printer.Fprintln(tabw, "API GROUP\tCURRENT VERSION\tPREFERRED VERSION\tMANUAL UPGRADE REQUIRED")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, state := range versionStates {
 | 
					 | 
				
			||||||
		printer.Fprintf(tabw,
 | 
					 | 
				
			||||||
			"%s\t%s\t%s\t%s\n",
 | 
					 | 
				
			||||||
			state.Group,
 | 
					 | 
				
			||||||
			strOrDash(state.CurrentVersion),
 | 
					 | 
				
			||||||
			strOrDash(state.PreferredVersion),
 | 
					 | 
				
			||||||
			yesOrNo(state.ManualUpgradeRequired),
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tabw.Flush()
 | 
					 | 
				
			||||||
	printLineSeparator(w, printer)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,9 @@ import (
 | 
				
			|||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/diff"
 | 
				
			||||||
 | 
						outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
 | 
				
			||||||
 | 
						outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -67,10 +70,26 @@ func TestSortedSliceFromStringIntMap(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO Think about modifying this test to be less verbose checking b/c it can be brittle.
 | 
					// TODO Think about modifying this test to be less verbose checking b/c it can be brittle.
 | 
				
			||||||
func TestPrintAvailableUpgrades(t *testing.T) {
 | 
					func TestPrintUpgradePlan(t *testing.T) {
 | 
				
			||||||
 | 
						versionStates := []outputapiv1alpha3.ComponentConfigVersionState{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Group:                 "kubeproxy.config.k8s.io",
 | 
				
			||||||
 | 
								CurrentVersion:        "v1alpha1",
 | 
				
			||||||
 | 
								PreferredVersion:      "v1alpha1",
 | 
				
			||||||
 | 
								ManualUpgradeRequired: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Group:                 "kubelet.config.k8s.io",
 | 
				
			||||||
 | 
								CurrentVersion:        "v1beta1",
 | 
				
			||||||
 | 
								PreferredVersion:      "v1beta1",
 | 
				
			||||||
 | 
								ManualUpgradeRequired: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var tests = []struct {
 | 
						var tests = []struct {
 | 
				
			||||||
		name          string
 | 
							name          string
 | 
				
			||||||
		upgrades      []upgrade.Upgrade
 | 
							upgrades      []upgrade.Upgrade
 | 
				
			||||||
 | 
							versionStates []outputapiv1alpha3.ComponentConfigVersionState
 | 
				
			||||||
		buf           *bytes.Buffer
 | 
							buf           *bytes.Buffer
 | 
				
			||||||
		expectedBytes []byte
 | 
							expectedBytes []byte
 | 
				
			||||||
		externalEtcd  bool
 | 
							externalEtcd  bool
 | 
				
			||||||
@@ -97,6 +116,7 @@ func TestPrintAvailableUpgrades(t *testing.T) {
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.18.1   v1.18.4
 | 
					kubelet     1 x v1.18.1   v1.18.4
 | 
				
			||||||
@@ -119,6 +139,17 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.18.4
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_____________________________________________________________________
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -143,6 +174,7 @@ _____________________________________________________________________
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.18.4   v1.19.0
 | 
					kubelet     1 x v1.18.4   v1.19.0
 | 
				
			||||||
@@ -165,6 +197,17 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.19.0
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_____________________________________________________________________
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -207,6 +250,7 @@ _____________________________________________________________________
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.18.3   v1.18.5
 | 
					kubelet     1 x v1.18.3   v1.18.5
 | 
				
			||||||
@@ -249,6 +293,17 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.19.0
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_____________________________________________________________________
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -273,6 +328,7 @@ _____________________________________________________________________
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.18.5   v1.19.0-beta.1
 | 
					kubelet     1 x v1.18.5   v1.19.0-beta.1
 | 
				
			||||||
@@ -295,6 +351,17 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.19.0
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_____________________________________________________________________
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -319,6 +386,7 @@ _____________________________________________________________________
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.18.5   v1.19.0-rc.1
 | 
					kubelet     1 x v1.18.5   v1.19.0-rc.1
 | 
				
			||||||
@@ -341,6 +409,17 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.19.0
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_____________________________________________________________________
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -366,6 +445,7 @@ _____________________________________________________________________
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.19.2   v1.19.3
 | 
					kubelet     1 x v1.19.2   v1.19.3
 | 
				
			||||||
@@ -389,6 +469,17 @@ 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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -414,7 +505,8 @@ _____________________________________________________________________
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			externalEtcd: true,
 | 
								versionStates: versionStates,
 | 
				
			||||||
 | 
								externalEtcd:  true,
 | 
				
			||||||
			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   CURRENT       TARGET
 | 
				
			||||||
kubelet     1 x v1.19.2   v1.19.3
 | 
					kubelet     1 x v1.19.2   v1.19.3
 | 
				
			||||||
@@ -436,30 +528,38 @@ 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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`),
 | 
					`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, rt := range tests {
 | 
						for _, rt := range tests {
 | 
				
			||||||
		t.Run(rt.name, func(t *testing.T) {
 | 
							t.Run(rt.name, func(t *testing.T) {
 | 
				
			||||||
			rt.buf = bytes.NewBufferString("")
 | 
								rt.buf = bytes.NewBufferString("")
 | 
				
			||||||
			outputFlags := newUpgradePlanPrintFlags(output.TextOutput)
 | 
								outputFlags := output.NewOutputFlags(&upgradePlanTextPrintFlags{}).WithTypeSetter(outputapischeme.Scheme).WithDefaultOutput(output.TextOutput)
 | 
				
			||||||
			printer, err := outputFlags.ToPrinter()
 | 
								printer, err := outputFlags.ToPrinter()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				t.Errorf("failed ToPrinter, err: %+v", err)
 | 
									t.Errorf("failed ToPrinter, err: %+v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Generate and print upgrade plans
 | 
								plan := genUpgradePlan(rt.upgrades, rt.versionStates, rt.externalEtcd)
 | 
				
			||||||
			for _, up := range rt.upgrades {
 | 
								if err := printer.PrintObj(plan, rt.buf); err != nil {
 | 
				
			||||||
				plan, unstableVersionFlag, err := genUpgradePlan(&up, rt.externalEtcd)
 | 
									t.Errorf("unexpected error when print object: %v", err)
 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					t.Errorf("failed genUpgradePlan, err: %+v", err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				printUpgradePlan(&up, plan, unstableVersionFlag, rt.externalEtcd, rt.buf, printer)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			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 PrintAvailableUpgrades:\n\texpected: %q\n\n\tactual  : %q",
 | 
										"failed PrintUpgradePlan:\n\texpected: %q\n\n\tactual  : %q",
 | 
				
			||||||
					string(rt.expectedBytes),
 | 
										string(rt.expectedBytes),
 | 
				
			||||||
					string(actualBytes),
 | 
										string(actualBytes),
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
@@ -468,7 +568,7 @@ _____________________________________________________________________
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPrintAvailableUpgradesStructured(t *testing.T) {
 | 
					func TestPrintUpgradePlanStructured(t *testing.T) {
 | 
				
			||||||
	upgrades := []upgrade.Upgrade{
 | 
						upgrades := []upgrade.Upgrade{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Description: "version in the v1.8 series",
 | 
								Description: "version in the v1.8 series",
 | 
				
			||||||
@@ -490,6 +590,21 @@ func TestPrintAvailableUpgradesStructured(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						versionStates := []outputapiv1alpha3.ComponentConfigVersionState{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Group:                 "kubeproxy.config.k8s.io",
 | 
				
			||||||
 | 
								CurrentVersion:        "v1alpha1",
 | 
				
			||||||
 | 
								PreferredVersion:      "v1alpha1",
 | 
				
			||||||
 | 
								ManualUpgradeRequired: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Group:                 "kubelet.config.k8s.io",
 | 
				
			||||||
 | 
								CurrentVersion:        "v1beta1",
 | 
				
			||||||
 | 
								PreferredVersion:      "v1beta1",
 | 
				
			||||||
 | 
								ManualUpgradeRequired: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var tests = []struct {
 | 
						var tests = []struct {
 | 
				
			||||||
		name         string
 | 
							name         string
 | 
				
			||||||
		outputFormat string
 | 
							outputFormat string
 | 
				
			||||||
@@ -502,81 +617,117 @@ func TestPrintAvailableUpgradesStructured(t *testing.T) {
 | 
				
			|||||||
			outputFormat: "json",
 | 
								outputFormat: "json",
 | 
				
			||||||
			expected: `{
 | 
								expected: `{
 | 
				
			||||||
    "kind": "UpgradePlan",
 | 
					    "kind": "UpgradePlan",
 | 
				
			||||||
    "apiVersion": "output.kubeadm.k8s.io/v1alpha2",
 | 
					    "apiVersion": "output.kubeadm.k8s.io/v1alpha3",
 | 
				
			||||||
    "components": [
 | 
					    "availableUpgrades": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "kubelet",
 | 
					            "description": "version in the v1.8 series",
 | 
				
			||||||
            "currentVersion": "1 x v1.8.1",
 | 
					            "components": [
 | 
				
			||||||
            "newVersion": "v1.8.3"
 | 
					                {
 | 
				
			||||||
        },
 | 
					                    "name": "kubelet",
 | 
				
			||||||
        {
 | 
					                    "currentVersion": "1 x v1.8.1",
 | 
				
			||||||
            "name": "kube-apiserver",
 | 
					                    "newVersion": "v1.8.3"
 | 
				
			||||||
            "currentVersion": "v1.8.1",
 | 
					                },
 | 
				
			||||||
            "newVersion": "v1.8.3"
 | 
					                {
 | 
				
			||||||
        },
 | 
					                    "name": "kube-apiserver",
 | 
				
			||||||
        {
 | 
					                    "currentVersion": "v1.8.1",
 | 
				
			||||||
            "name": "kube-controller-manager",
 | 
					                    "newVersion": "v1.8.3"
 | 
				
			||||||
            "currentVersion": "v1.8.1",
 | 
					                },
 | 
				
			||||||
            "newVersion": "v1.8.3"
 | 
					                {
 | 
				
			||||||
        },
 | 
					                    "name": "kube-controller-manager",
 | 
				
			||||||
        {
 | 
					                    "currentVersion": "v1.8.1",
 | 
				
			||||||
            "name": "kube-scheduler",
 | 
					                    "newVersion": "v1.8.3"
 | 
				
			||||||
            "currentVersion": "v1.8.1",
 | 
					                },
 | 
				
			||||||
            "newVersion": "v1.8.3"
 | 
					                {
 | 
				
			||||||
        },
 | 
					                    "name": "kube-scheduler",
 | 
				
			||||||
        {
 | 
					                    "currentVersion": "v1.8.1",
 | 
				
			||||||
            "name": "kube-proxy",
 | 
					                    "newVersion": "v1.8.3"
 | 
				
			||||||
            "currentVersion": "v1.8.1",
 | 
					                },
 | 
				
			||||||
            "newVersion": "v1.8.3"
 | 
					                {
 | 
				
			||||||
        },
 | 
					                    "name": "kube-proxy",
 | 
				
			||||||
        {
 | 
					                    "currentVersion": "v1.8.1",
 | 
				
			||||||
            "name": "CoreDNS",
 | 
					                    "newVersion": "v1.8.3"
 | 
				
			||||||
            "currentVersion": "1.14.5",
 | 
					                },
 | 
				
			||||||
            "newVersion": "1.14.5"
 | 
					                {
 | 
				
			||||||
        },
 | 
					                    "name": "CoreDNS",
 | 
				
			||||||
        {
 | 
					                    "currentVersion": "1.14.5",
 | 
				
			||||||
            "name": "etcd",
 | 
					                    "newVersion": "1.14.5"
 | 
				
			||||||
            "currentVersion": "3.0.17",
 | 
					                },
 | 
				
			||||||
            "newVersion": "3.0.17"
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "kubeadm",
 | 
				
			||||||
 | 
					                    "currentVersion": "v1.8.2",
 | 
				
			||||||
 | 
					                    "newVersion": "v1.8.3"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "etcd",
 | 
				
			||||||
 | 
					                    "currentVersion": "3.0.17",
 | 
				
			||||||
 | 
					                    "newVersion": "3.0.17"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "configVersions": null
 | 
					    "configVersions": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "group": "kubeproxy.config.k8s.io",
 | 
				
			||||||
 | 
					            "currentVersion": "v1alpha1",
 | 
				
			||||||
 | 
					            "preferredVersion": "v1alpha1",
 | 
				
			||||||
 | 
					            "manualUpgradeRequired": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "group": "kubelet.config.k8s.io",
 | 
				
			||||||
 | 
					            "currentVersion": "v1beta1",
 | 
				
			||||||
 | 
					            "preferredVersion": "v1beta1",
 | 
				
			||||||
 | 
					            "manualUpgradeRequired": false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
`,
 | 
					`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:         "YAML output",
 | 
								name:         "YAML output",
 | 
				
			||||||
			outputFormat: "yaml",
 | 
								outputFormat: "yaml",
 | 
				
			||||||
			expected: `apiVersion: output.kubeadm.k8s.io/v1alpha2
 | 
								expected: `apiVersion: output.kubeadm.k8s.io/v1alpha3
 | 
				
			||||||
components:
 | 
					availableUpgrades:
 | 
				
			||||||
- currentVersion: 1 x v1.8.1
 | 
					- components:
 | 
				
			||||||
  name: kubelet
 | 
					  - currentVersion: 1 x v1.8.1
 | 
				
			||||||
  newVersion: v1.8.3
 | 
					    name: kubelet
 | 
				
			||||||
- currentVersion: v1.8.1
 | 
					    newVersion: v1.8.3
 | 
				
			||||||
  name: kube-apiserver
 | 
					  - currentVersion: v1.8.1
 | 
				
			||||||
  newVersion: v1.8.3
 | 
					    name: kube-apiserver
 | 
				
			||||||
- currentVersion: v1.8.1
 | 
					    newVersion: v1.8.3
 | 
				
			||||||
  name: kube-controller-manager
 | 
					  - currentVersion: v1.8.1
 | 
				
			||||||
  newVersion: v1.8.3
 | 
					    name: kube-controller-manager
 | 
				
			||||||
- currentVersion: v1.8.1
 | 
					    newVersion: v1.8.3
 | 
				
			||||||
  name: kube-scheduler
 | 
					  - currentVersion: v1.8.1
 | 
				
			||||||
  newVersion: v1.8.3
 | 
					    name: kube-scheduler
 | 
				
			||||||
- currentVersion: v1.8.1
 | 
					    newVersion: v1.8.3
 | 
				
			||||||
  name: kube-proxy
 | 
					  - currentVersion: v1.8.1
 | 
				
			||||||
  newVersion: v1.8.3
 | 
					    name: kube-proxy
 | 
				
			||||||
- currentVersion: 1.14.5
 | 
					    newVersion: v1.8.3
 | 
				
			||||||
  name: CoreDNS
 | 
					  - currentVersion: 1.14.5
 | 
				
			||||||
  newVersion: 1.14.5
 | 
					    name: CoreDNS
 | 
				
			||||||
- currentVersion: 3.0.17
 | 
					    newVersion: 1.14.5
 | 
				
			||||||
  name: etcd
 | 
					  - currentVersion: v1.8.2
 | 
				
			||||||
  newVersion: 3.0.17
 | 
					    name: kubeadm
 | 
				
			||||||
configVersions: null
 | 
					    newVersion: v1.8.3
 | 
				
			||||||
 | 
					  - currentVersion: 3.0.17
 | 
				
			||||||
 | 
					    name: etcd
 | 
				
			||||||
 | 
					    newVersion: 3.0.17
 | 
				
			||||||
 | 
					  description: version in the v1.8 series
 | 
				
			||||||
 | 
					configVersions:
 | 
				
			||||||
 | 
					- currentVersion: v1alpha1
 | 
				
			||||||
 | 
					  group: kubeproxy.config.k8s.io
 | 
				
			||||||
 | 
					  manualUpgradeRequired: false
 | 
				
			||||||
 | 
					  preferredVersion: v1alpha1
 | 
				
			||||||
 | 
					- currentVersion: v1beta1
 | 
				
			||||||
 | 
					  group: kubelet.config.k8s.io
 | 
				
			||||||
 | 
					  manualUpgradeRequired: false
 | 
				
			||||||
 | 
					  preferredVersion: v1beta1
 | 
				
			||||||
kind: UpgradePlan
 | 
					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   CURRENT      TARGET
 | 
				
			||||||
kubelet     1 x v1.8.1   v1.8.3
 | 
					kubelet     1 x v1.8.1   v1.8.3
 | 
				
			||||||
@@ -599,6 +750,17 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.8.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
 | 
				
			||||||
 | 
					_____________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`,
 | 
					`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -606,24 +768,21 @@ _____________________________________________________________________
 | 
				
			|||||||
	for _, rt := range tests {
 | 
						for _, rt := range tests {
 | 
				
			||||||
		t.Run(rt.name, func(t *testing.T) {
 | 
							t.Run(rt.name, func(t *testing.T) {
 | 
				
			||||||
			rt.buf = bytes.NewBufferString("")
 | 
								rt.buf = bytes.NewBufferString("")
 | 
				
			||||||
			outputFlags := newUpgradePlanPrintFlags(rt.outputFormat)
 | 
								outputFlags := output.NewOutputFlags(&upgradePlanTextPrintFlags{}).WithTypeSetter(outputapischeme.Scheme).WithDefaultOutput(rt.outputFormat)
 | 
				
			||||||
			printer, err := outputFlags.ToPrinter()
 | 
								printer, err := outputFlags.ToPrinter()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				t.Errorf("failed ToPrinter, err: %+v", err)
 | 
									t.Errorf("failed ToPrinter, err: %+v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Generate and print upgrade plans
 | 
								plan := genUpgradePlan(upgrades, versionStates, false)
 | 
				
			||||||
			for _, up := range upgrades {
 | 
								if err := printer.PrintObj(plan, rt.buf); err != nil {
 | 
				
			||||||
				plan, unstableVersionFlag, err := genUpgradePlan(&up, rt.externalEtcd)
 | 
									t.Errorf("unexpected error when print object: %v", err)
 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					t.Errorf("failed genUpgradePlan, err: %+v", err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				printUpgradePlan(&up, plan, unstableVersionFlag, rt.externalEtcd, rt.buf, printer)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			actual := rt.buf.String()
 | 
								actual := rt.buf.String()
 | 
				
			||||||
			if actual != rt.expected {
 | 
								if actual != rt.expected {
 | 
				
			||||||
				t.Errorf("failed PrintAvailableUpgrades:\n\nexpected:\n%s\n\nactual:\n%s", rt.expected, actual)
 | 
					
 | 
				
			||||||
 | 
									t.Errorf("failed PrintUpgradePlan:\n\nexpected:\n%s\n\nactual:\n%s\n\ndiff:\n%s", rt.expected, actual, diff.StringDiff(actual, rt.expected))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ import (
 | 
				
			|||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
						kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
				
			||||||
	outputapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha2"
 | 
						outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
				
			||||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
						kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict"
 | 
				
			||||||
@@ -289,7 +289,7 @@ func FetchFromClusterWithLocalOverwrites(clusterCfg *kubeadmapi.ClusterConfigura
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetVersionStates returns a slice of ComponentConfigVersionState structs
 | 
					// GetVersionStates returns a slice of ComponentConfigVersionState structs
 | 
				
			||||||
// describing all supported component config groups that were identified on the cluster
 | 
					// describing all supported component config groups that were identified on the cluster
 | 
				
			||||||
func GetVersionStates(clusterCfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) ([]outputapiv1alpha2.ComponentConfigVersionState, error) {
 | 
					func GetVersionStates(clusterCfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) ([]outputapiv1alpha3.ComponentConfigVersionState, error) {
 | 
				
			||||||
	// We don't want to modify clusterCfg so we make a working deep copy of it.
 | 
						// We don't want to modify clusterCfg so we make a working deep copy of it.
 | 
				
			||||||
	// Also, we don't want the defaulted component configs so we get rid of them.
 | 
						// Also, we don't want the defaulted component configs so we get rid of them.
 | 
				
			||||||
	scratchClusterCfg := clusterCfg.DeepCopy()
 | 
						scratchClusterCfg := clusterCfg.DeepCopy()
 | 
				
			||||||
@@ -301,12 +301,12 @@ func GetVersionStates(clusterCfg *kubeadmapi.ClusterConfiguration, client client
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	results := []outputapiv1alpha2.ComponentConfigVersionState{}
 | 
						results := []outputapiv1alpha3.ComponentConfigVersionState{}
 | 
				
			||||||
	for _, handler := range known {
 | 
						for _, handler := range known {
 | 
				
			||||||
		group := handler.GroupVersion.Group
 | 
							group := handler.GroupVersion.Group
 | 
				
			||||||
		if _, ok := scratchClusterCfg.ComponentConfigs[group]; ok {
 | 
							if _, ok := scratchClusterCfg.ComponentConfigs[group]; ok {
 | 
				
			||||||
			// Normally loaded component config. No manual upgrade required on behalf of users.
 | 
								// Normally loaded component config. No manual upgrade required on behalf of users.
 | 
				
			||||||
			results = append(results, outputapiv1alpha2.ComponentConfigVersionState{
 | 
								results = append(results, outputapiv1alpha3.ComponentConfigVersionState{
 | 
				
			||||||
				Group:            group,
 | 
									Group:            group,
 | 
				
			||||||
				CurrentVersion:   handler.GroupVersion.Version, // Currently kubeadm supports only one version per API
 | 
									CurrentVersion:   handler.GroupVersion.Version, // Currently kubeadm supports only one version per API
 | 
				
			||||||
				PreferredVersion: handler.GroupVersion.Version, // group so we can get away with these being the same
 | 
									PreferredVersion: handler.GroupVersion.Version, // group so we can get away with these being the same
 | 
				
			||||||
@@ -315,7 +315,7 @@ func GetVersionStates(clusterCfg *kubeadmapi.ClusterConfiguration, client client
 | 
				
			|||||||
			// This config was either not present (user did not install an addon) or the config was unsupported kubeadm
 | 
								// This config was either not present (user did not install an addon) or the config was unsupported kubeadm
 | 
				
			||||||
			// generated one and is therefore skipped so we can automatically re-generate it (no action required on
 | 
								// generated one and is therefore skipped so we can automatically re-generate it (no action required on
 | 
				
			||||||
			// behalf of the user).
 | 
								// behalf of the user).
 | 
				
			||||||
			results = append(results, outputapiv1alpha2.ComponentConfigVersionState{
 | 
								results = append(results, outputapiv1alpha3.ComponentConfigVersionState{
 | 
				
			||||||
				Group:            group,
 | 
									Group:            group,
 | 
				
			||||||
				PreferredVersion: handler.GroupVersion.Version,
 | 
									PreferredVersion: handler.GroupVersion.Version,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ import (
 | 
				
			|||||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
						kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
				
			||||||
	kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
						kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
				
			||||||
	kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
 | 
						kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
 | 
				
			||||||
	outputapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha2"
 | 
						outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
				
			||||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
						kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -612,7 +612,7 @@ func TestFetchFromClusterWithLocalOverwrites(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetVersionStates(t *testing.T) {
 | 
					func TestGetVersionStates(t *testing.T) {
 | 
				
			||||||
	fakeKnownContext(func() {
 | 
						fakeKnownContext(func() {
 | 
				
			||||||
		versionStateCurrent := outputapiv1alpha2.ComponentConfigVersionState{
 | 
							versionStateCurrent := outputapiv1alpha3.ComponentConfigVersionState{
 | 
				
			||||||
			Group:            kubeadmapiv1.GroupName,
 | 
								Group:            kubeadmapiv1.GroupName,
 | 
				
			||||||
			CurrentVersion:   currentClusterConfigVersion,
 | 
								CurrentVersion:   currentClusterConfigVersion,
 | 
				
			||||||
			PreferredVersion: currentClusterConfigVersion,
 | 
								PreferredVersion: currentClusterConfigVersion,
 | 
				
			||||||
@@ -622,7 +622,7 @@ func TestGetVersionStates(t *testing.T) {
 | 
				
			|||||||
			desc        string
 | 
								desc        string
 | 
				
			||||||
			obj         runtime.Object
 | 
								obj         runtime.Object
 | 
				
			||||||
			expectedErr bool
 | 
								expectedErr bool
 | 
				
			||||||
			expected    outputapiv1alpha2.ComponentConfigVersionState
 | 
								expected    outputapiv1alpha3.ComponentConfigVersionState
 | 
				
			||||||
		}{
 | 
							}{
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				desc:     "appropriate cluster object",
 | 
									desc:     "appropriate cluster object",
 | 
				
			||||||
@@ -642,7 +642,7 @@ func TestGetVersionStates(t *testing.T) {
 | 
				
			|||||||
			{
 | 
								{
 | 
				
			||||||
				desc: "old signed config",
 | 
									desc: "old signed config",
 | 
				
			||||||
				obj:  testClusterConfigMap(oldFooClusterConfig, true),
 | 
									obj:  testClusterConfigMap(oldFooClusterConfig, true),
 | 
				
			||||||
				expected: outputapiv1alpha2.ComponentConfigVersionState{
 | 
									expected: outputapiv1alpha3.ComponentConfigVersionState{
 | 
				
			||||||
					Group:            kubeadmapiv1.GroupName,
 | 
										Group:            kubeadmapiv1.GroupName,
 | 
				
			||||||
					CurrentVersion:   "", // The config is treated as if it's missing
 | 
										CurrentVersion:   "", // The config is treated as if it's missing
 | 
				
			||||||
					PreferredVersion: currentClusterConfigVersion,
 | 
										PreferredVersion: currentClusterConfigVersion,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -340,6 +340,8 @@ const (
 | 
				
			|||||||
	CoreDNS = "CoreDNS"
 | 
						CoreDNS = "CoreDNS"
 | 
				
			||||||
	// Kubelet defines variable used internally when referring to the Kubelet
 | 
						// Kubelet defines variable used internally when referring to the Kubelet
 | 
				
			||||||
	Kubelet = "kubelet"
 | 
						Kubelet = "kubelet"
 | 
				
			||||||
 | 
						// Kubeadm defines variable used internally when referring to the kubeadm component
 | 
				
			||||||
 | 
						Kubeadm = "kubeadm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// KubeCertificatesVolumeName specifies the name for the Volume that is used for injecting certificates to control plane components (can be both a hostPath volume or a projected, all-in-one volume)
 | 
						// KubeCertificatesVolumeName specifies the name for the Volume that is used for injecting certificates to control plane components (can be both a hostPath volume or a projected, all-in-one volume)
 | 
				
			||||||
	KubeCertificatesVolumeName = "k8s-certs"
 | 
						KubeCertificatesVolumeName = "k8s-certs"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -144,9 +144,6 @@ type Printer interface {
 | 
				
			|||||||
	Fprintln(writer io.Writer, args ...interface{}) (n int, err error)
 | 
						Fprintln(writer io.Writer, args ...interface{}) (n int, err error)
 | 
				
			||||||
	Printf(format string, args ...interface{}) (n int, err error)
 | 
						Printf(format string, args ...interface{}) (n int, err error)
 | 
				
			||||||
	Println(args ...interface{}) (n int, err error)
 | 
						Println(args ...interface{}) (n int, err error)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	Flush(writer io.Writer, last bool)
 | 
					 | 
				
			||||||
	Close(writer io.Writer)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TextPrinter implements Printer interface for generic text output
 | 
					// TextPrinter implements Printer interface for generic text output
 | 
				
			||||||
@@ -179,14 +176,6 @@ func (tp *TextPrinter) Println(args ...interface{}) (n int, err error) {
 | 
				
			|||||||
	return fmt.Println(args...)
 | 
						return fmt.Println(args...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Flush writes any buffered data
 | 
					 | 
				
			||||||
func (tp *TextPrinter) Flush(writer io.Writer, last bool) {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close flushes any buffered data and closes the printer
 | 
					 | 
				
			||||||
func (tp *TextPrinter) Close(writer io.Writer) {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ResourcePrinterWrapper wraps ResourcePrinter and implements Printer interface
 | 
					// ResourcePrinterWrapper wraps ResourcePrinter and implements Printer interface
 | 
				
			||||||
type ResourcePrinterWrapper struct {
 | 
					type ResourcePrinterWrapper struct {
 | 
				
			||||||
	Printer printers.ResourcePrinter
 | 
						Printer printers.ResourcePrinter
 | 
				
			||||||
@@ -200,14 +189,6 @@ func NewResourcePrinterWrapper(resourcePrinter printers.ResourcePrinter, err err
 | 
				
			|||||||
	return &ResourcePrinterWrapper{Printer: resourcePrinter}, nil
 | 
						return &ResourcePrinterWrapper{Printer: resourcePrinter}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Flush writes any buffered data
 | 
					 | 
				
			||||||
func (rpw *ResourcePrinterWrapper) Flush(writer io.Writer, last bool) {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close flushes any buffered data and closes the printer
 | 
					 | 
				
			||||||
func (rpw *ResourcePrinterWrapper) Close(writer io.Writer) {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PrintObj is an implementation of ResourcePrinter.PrintObj that calls underlying printer API
 | 
					// PrintObj is an implementation of ResourcePrinter.PrintObj that calls underlying printer API
 | 
				
			||||||
func (rpw *ResourcePrinterWrapper) PrintObj(obj runtime.Object, writer io.Writer) error {
 | 
					func (rpw *ResourcePrinterWrapper) PrintObj(obj runtime.Object, writer io.Writer) error {
 | 
				
			||||||
	return rpw.Printer.PrintObj(obj, writer)
 | 
						return rpw.Printer.PrintObj(obj, writer)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user