Merge pull request #123068 from calvin0327/upgrade-configuration
kubeadm: implementation of UpgradeConfiguration API types
This commit is contained in:
@@ -41,6 +41,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
fuzzJoinConfiguration,
|
||||
fuzzJoinControlPlane,
|
||||
fuzzResetConfiguration,
|
||||
fuzzUpgradeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,3 +153,13 @@ func fuzzResetConfiguration(obj *kubeadm.ResetConfiguration, c fuzz.Continue) {
|
||||
obj.CertificatesDir = "/tmp"
|
||||
kubeadm.SetDefaultTimeouts(&obj.Timeouts)
|
||||
}
|
||||
|
||||
func fuzzUpgradeConfiguration(obj *kubeadm.UpgradeConfiguration, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
obj.Node.EtcdUpgrade = ptr.To(true)
|
||||
obj.Apply.EtcdUpgrade = ptr.To(true)
|
||||
obj.Apply.CertificateRenewal = ptr.To(false)
|
||||
obj.Node.CertificateRenewal = ptr.To(false)
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&ClusterConfiguration{},
|
||||
&JoinConfiguration{},
|
||||
&ResetConfiguration{},
|
||||
&UpgradeConfiguration{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ type InitConfiguration struct {
|
||||
// the `json:"-"` tag in the external variant of these API types.
|
||||
ClusterConfiguration `json:"-"`
|
||||
|
||||
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
||||
// BootstrapTokens is respected at "kubeadm init" time and describes a set of Bootstrap Tokens to create.
|
||||
BootstrapTokens []bootstraptokenv1.BootstrapToken
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
@@ -221,7 +221,7 @@ type APIEndpoint struct {
|
||||
// NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join"
|
||||
type NodeRegistrationOptions struct {
|
||||
|
||||
// Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm join` operation.
|
||||
// Name is the `.Metadata.Name` field of the Node API object that will be created in this "kubeadm init" or "kubeadm join" operation.
|
||||
// This field is also used in the CommonName field of the kubelet's client certificate to the API server.
|
||||
// Defaults to the hostname of the node if not provided.
|
||||
Name string
|
||||
@@ -541,6 +541,125 @@ type ResetConfiguration struct {
|
||||
Timeouts *Timeouts
|
||||
}
|
||||
|
||||
// UpgradeApplyConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade apply" command.
|
||||
type UpgradeApplyConfiguration struct {
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
KubernetesVersion string
|
||||
|
||||
// AllowExperimentalUpgrades instructs kubeadm to show unstable versions of Kubernetes as an upgrade
|
||||
// alternative and allows upgrading to an alpha/beta/release candidate version of Kubernetes.
|
||||
// Default: false
|
||||
AllowExperimentalUpgrades *bool
|
||||
|
||||
// Enable AllowRCUpgrades will show release candidate versions of Kubernetes as an upgrade alternative and
|
||||
// allows upgrading to a release candidate version of Kubernetes.
|
||||
AllowRCUpgrades *bool
|
||||
|
||||
// CertificateRenewal instructs kubeadm to execute certificate renewal during upgrades.
|
||||
CertificateRenewal *bool
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
DryRun *bool
|
||||
|
||||
// EtcdUpgrade instructs kubeadm to execute etcd upgrade during upgrades.
|
||||
EtcdUpgrade *bool
|
||||
|
||||
// ForceUpgrade flag instructs kubeadm to upgrade the cluster without prompting for confirmation.
|
||||
ForceUpgrade *bool
|
||||
|
||||
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, e.g. 'IsPrivilegedUser,Swap'.
|
||||
// Value 'all' ignores errors from all checks.
|
||||
IgnorePreflightErrors []string
|
||||
|
||||
// Patches contains options related to applying patches to components deployed by kubeadm during "kubeadm upgrade".
|
||||
Patches *Patches
|
||||
|
||||
// PrintConfig specifies whether the configuration file that will be used in the upgrade should be printed or not.
|
||||
PrintConfig *bool
|
||||
|
||||
// SkipPhases is a list of phases to skip during command execution.
|
||||
// NOTE: This field is currently ignored for "kubeadm upgrade apply", but in the future it will be supported.
|
||||
SkipPhases []string
|
||||
}
|
||||
|
||||
// UpgradeDiffConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade diff" command.
|
||||
type UpgradeDiffConfiguration struct {
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
KubernetesVersion string
|
||||
|
||||
// DiffContextLines is the number of lines of context in the diff.
|
||||
DiffContextLines int
|
||||
}
|
||||
|
||||
// UpgradeNodeConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade node" command.
|
||||
type UpgradeNodeConfiguration struct {
|
||||
// CertificateRenewal instructs kubeadm to execute certificate renewal during upgrades.
|
||||
CertificateRenewal *bool
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
DryRun *bool
|
||||
|
||||
// EtcdUpgrade instructs kubeadm to execute etcd upgrade during upgrades.
|
||||
EtcdUpgrade *bool
|
||||
|
||||
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, e.g. 'IsPrivilegedUser,Swap'.
|
||||
// Value 'all' ignores errors from all checks.
|
||||
IgnorePreflightErrors []string
|
||||
|
||||
// SkipPhases is a list of phases to skip during command execution.
|
||||
// The list of phases can be obtained with the "kubeadm upgrade node phase --help" command.
|
||||
SkipPhases []string
|
||||
|
||||
// Patches contains options related to applying patches to components deployed by kubeadm during "kubeadm upgrade".
|
||||
Patches *Patches
|
||||
}
|
||||
|
||||
// UpgradePlanConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade plan" command.
|
||||
type UpgradePlanConfiguration struct {
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
// +optional
|
||||
KubernetesVersion string
|
||||
|
||||
// AllowExperimentalUpgrades instructs kubeadm to show unstable versions of Kubernetes as an upgrade
|
||||
// alternative and allows upgrading to an alpha/beta/release candidate version of Kubernetes.
|
||||
// Default: false
|
||||
// +optional
|
||||
AllowExperimentalUpgrades *bool
|
||||
|
||||
// Enable AllowRCUpgrades will show release candidate versions of Kubernetes as an upgrade alternative and
|
||||
// allows upgrading to a release candidate version of Kubernetes.
|
||||
AllowRCUpgrades *bool
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
DryRun *bool
|
||||
|
||||
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, e.g. 'IsPrivilegedUser,Swap'.
|
||||
// Value 'all' ignores errors from all checks.
|
||||
IgnorePreflightErrors []string
|
||||
|
||||
// PrintConfig specifies whether the configuration file that will be used in the upgrade should be printed or not.
|
||||
PrintConfig *bool
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// UpgradeConfiguration contains a list of options that are specific to "kubeadm upgrade" subcommands.
|
||||
type UpgradeConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// Apply holds a list of options that are specific to the "kubeadm upgrade apply" command.
|
||||
Apply UpgradeApplyConfiguration
|
||||
|
||||
// Diff holds a list of options that are specific to the "kubeadm upgrade diff" command.
|
||||
Diff UpgradeDiffConfiguration
|
||||
|
||||
// Node holds a list of options that are specific to the "kubeadm upgrade node" command.
|
||||
Node UpgradeNodeConfiguration
|
||||
|
||||
// Plan holds a list of options that are specific to the "kubeadm upgrade plan" command.
|
||||
Plan UpgradePlanConfiguration
|
||||
}
|
||||
|
||||
const (
|
||||
// UnmountFlagMNTForce represents the flag "MNT_FORCE"
|
||||
UnmountFlagMNTForce = "MNT_FORCE"
|
||||
|
@@ -256,3 +256,22 @@ func SetDefaults_Timeouts(obj *Timeouts) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_UpgradeConfiguration assigns default values for the UpgradeConfiguration
|
||||
func SetDefaults_UpgradeConfiguration(obj *UpgradeConfiguration) {
|
||||
if obj.Node.EtcdUpgrade == nil {
|
||||
obj.Node.EtcdUpgrade = ptr.To(true)
|
||||
}
|
||||
|
||||
if obj.Node.CertificateRenewal == nil {
|
||||
obj.Node.CertificateRenewal = ptr.To(true)
|
||||
}
|
||||
|
||||
if obj.Apply.EtcdUpgrade == nil {
|
||||
obj.Apply.EtcdUpgrade = ptr.To(true)
|
||||
}
|
||||
|
||||
if obj.Apply.CertificateRenewal == nil {
|
||||
obj.Apply.CertificateRenewal = ptr.To(true)
|
||||
}
|
||||
}
|
||||
|
@@ -41,6 +41,9 @@ limitations under the License.
|
||||
// that can be used to configure various timeouts.
|
||||
// - Add the `NodeRegistration.ImagePullSerial` field in 'InitConfiguration` and `JoinConfiguration`, which
|
||||
// can be used to control if kubeadm pulls images serially or in parallel.
|
||||
// - The UpgradeConfiguration kubeadm API is now supported in v1beta4 when passing --config to "kubeadm upgrade" subcommands.
|
||||
// Usage of component configuration for kubelet and kube-proxy, InitConfiguration and ClusterConfiguration is deprecated
|
||||
// and will be ignored when passing --config to upgrade subcommands.
|
||||
//
|
||||
// Migration from old kubeadm config versions
|
||||
//
|
||||
|
@@ -49,6 +49,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&ClusterConfiguration{},
|
||||
&JoinConfiguration{},
|
||||
&ResetConfiguration{},
|
||||
&UpgradeConfiguration{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
|
@@ -597,3 +597,151 @@ type Timeouts struct {
|
||||
// +optional
|
||||
Discovery *metav1.Duration `json:"discovery,omitempty"`
|
||||
}
|
||||
|
||||
// UpgradeApplyConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade apply" command.
|
||||
type UpgradeApplyConfiguration struct {
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
// +optional
|
||||
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
|
||||
|
||||
// AllowExperimentalUpgrades instructs kubeadm to show unstable versions of Kubernetes as an upgrade
|
||||
// alternative and allows upgrading to an alpha/beta/release candidate version of Kubernetes.
|
||||
// Default: false
|
||||
// +optional
|
||||
AllowExperimentalUpgrades *bool `json:"allowExperimentalUpgrades,omitempty"`
|
||||
|
||||
// Enable AllowRCUpgrades will show release candidate versions of Kubernetes as an upgrade alternative and
|
||||
// allows upgrading to a release candidate version of Kubernetes.
|
||||
// +optional
|
||||
AllowRCUpgrades *bool `json:"allowRCUpgrades,omitempty"`
|
||||
|
||||
// CertificateRenewal instructs kubeadm to execute certificate renewal during upgrades.
|
||||
// Defaults to true.
|
||||
// +optional
|
||||
CertificateRenewal *bool `json:"certificateRenewal,omitempty"`
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
// +optional
|
||||
DryRun *bool `json:"dryRun,omitempty"`
|
||||
|
||||
// EtcdUpgrade instructs kubeadm to execute etcd upgrade during upgrades.
|
||||
// Defaults to true.
|
||||
// +optional
|
||||
EtcdUpgrade *bool `json:"etcdUpgrade,omitempty"`
|
||||
|
||||
// ForceUpgrade flag instructs kubeadm to upgrade the cluster without prompting for confirmation.
|
||||
// +optional
|
||||
ForceUpgrade *bool `json:"forceUpgrade,omitempty"`
|
||||
|
||||
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, e.g. 'IsPrivilegedUser,Swap'.
|
||||
// Value 'all' ignores errors from all checks.
|
||||
// +optional
|
||||
IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"`
|
||||
|
||||
// Patches contains options related to applying patches to components deployed by kubeadm during "kubeadm upgrade".
|
||||
// +optional
|
||||
Patches *Patches `json:"patches,omitempty"`
|
||||
|
||||
// PrintConfig specifies whether the configuration file that will be used in the upgrade should be printed or not.
|
||||
// +optional
|
||||
PrintConfig *bool `json:"printConfig,omitempty"`
|
||||
|
||||
// SkipPhases is a list of phases to skip during command execution.
|
||||
// NOTE: This field is currently ignored for "kubeadm upgrade apply", but in the future it will be supported.
|
||||
SkipPhases []string
|
||||
}
|
||||
|
||||
// UpgradeDiffConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade diff" command.
|
||||
type UpgradeDiffConfiguration struct {
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
// +optional
|
||||
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
|
||||
|
||||
// DiffContextLines is the number of lines of context in the diff.
|
||||
// +optional
|
||||
DiffContextLines int `json:"contextLines,omitempty"`
|
||||
}
|
||||
|
||||
// UpgradeNodeConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade node" command.
|
||||
type UpgradeNodeConfiguration struct {
|
||||
// CertificateRenewal instructs kubeadm to execute certificate renewal during upgrades.
|
||||
// Defaults to true.
|
||||
// +optional
|
||||
CertificateRenewal *bool `json:"certificateRenewal,omitempty"`
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
// +optional
|
||||
DryRun *bool `json:"dryRun,omitempty"`
|
||||
|
||||
// EtcdUpgrade instructs kubeadm to execute etcd upgrade during upgrades.
|
||||
// Defaults to true.
|
||||
// +optional
|
||||
EtcdUpgrade *bool `json:"etcdUpgrade,omitempty"`
|
||||
|
||||
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, e.g. 'IsPrivilegedUser,Swap'.
|
||||
// Value 'all' ignores errors from all checks.
|
||||
// +optional
|
||||
IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"`
|
||||
|
||||
// SkipPhases is a list of phases to skip during command execution.
|
||||
// The list of phases can be obtained with the "kubeadm upgrade node phase --help" command.
|
||||
// +optional
|
||||
SkipPhases []string `json:"skipPhases,omitempty"`
|
||||
|
||||
// Patches contains options related to applying patches to components deployed by kubeadm during "kubeadm upgrade".
|
||||
// +optional
|
||||
Patches *Patches `json:"patches,omitempty"`
|
||||
}
|
||||
|
||||
// UpgradePlanConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade plan" command.
|
||||
type UpgradePlanConfiguration struct {
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
|
||||
|
||||
// AllowExperimentalUpgrades instructs kubeadm to show unstable versions of Kubernetes as an upgrade
|
||||
// alternative and allows upgrading to an alpha/beta/release candidate version of Kubernetes.
|
||||
// Default: false
|
||||
// +optional
|
||||
AllowExperimentalUpgrades *bool `json:"allowExperimentalUpgrades,omitempty"`
|
||||
|
||||
// Enable AllowRCUpgrades will show release candidate versions of Kubernetes as an upgrade alternative and
|
||||
// allows upgrading to a release candidate version of Kubernetes.
|
||||
// +optional
|
||||
AllowRCUpgrades *bool `json:"allowRCUpgrades,omitempty"`
|
||||
|
||||
// DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.
|
||||
// +optional
|
||||
DryRun *bool `json:"dryRun,omitempty"`
|
||||
|
||||
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, e.g. 'IsPrivilegedUser,Swap'.
|
||||
// Value 'all' ignores errors from all checks.
|
||||
// +optional
|
||||
IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"`
|
||||
|
||||
// PrintConfig specifies whether the configuration file that will be used in the upgrade should be printed or not.
|
||||
// +optional
|
||||
PrintConfig *bool `json:"printConfig,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// UpgradeConfiguration contains a list of options that are specific to "kubeadm upgrade" subcommands.
|
||||
type UpgradeConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// Apply holds a list of options that are specific to the "kubeadm upgrade apply" command.
|
||||
// +optional
|
||||
Apply UpgradeApplyConfiguration `json:"apply,omitempty"`
|
||||
|
||||
// Diff holds a list of options that are specific to the "kubeadm upgrade diff" command.
|
||||
// +optional
|
||||
Diff UpgradeDiffConfiguration `json:"diff,omitempty"`
|
||||
|
||||
// Node holds a list of options that are specific to the "kubeadm upgrade node" command.
|
||||
// +optional
|
||||
Node UpgradeNodeConfiguration `json:"node,omitempty"`
|
||||
|
||||
// Plan holds a list of options that are specific to the "kubeadm upgrade plan" command.
|
||||
// +optional
|
||||
Plan UpgradePlanConfiguration `json:"plan,omitempty"`
|
||||
}
|
||||
|
@@ -244,6 +244,56 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*UpgradeApplyConfiguration)(nil), (*kubeadm.UpgradeApplyConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta4_UpgradeApplyConfiguration_To_kubeadm_UpgradeApplyConfiguration(a.(*UpgradeApplyConfiguration), b.(*kubeadm.UpgradeApplyConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.UpgradeApplyConfiguration)(nil), (*UpgradeApplyConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_UpgradeApplyConfiguration_To_v1beta4_UpgradeApplyConfiguration(a.(*kubeadm.UpgradeApplyConfiguration), b.(*UpgradeApplyConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*UpgradeConfiguration)(nil), (*kubeadm.UpgradeConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta4_UpgradeConfiguration_To_kubeadm_UpgradeConfiguration(a.(*UpgradeConfiguration), b.(*kubeadm.UpgradeConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.UpgradeConfiguration)(nil), (*UpgradeConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_UpgradeConfiguration_To_v1beta4_UpgradeConfiguration(a.(*kubeadm.UpgradeConfiguration), b.(*UpgradeConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*UpgradeDiffConfiguration)(nil), (*kubeadm.UpgradeDiffConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta4_UpgradeDiffConfiguration_To_kubeadm_UpgradeDiffConfiguration(a.(*UpgradeDiffConfiguration), b.(*kubeadm.UpgradeDiffConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.UpgradeDiffConfiguration)(nil), (*UpgradeDiffConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_UpgradeDiffConfiguration_To_v1beta4_UpgradeDiffConfiguration(a.(*kubeadm.UpgradeDiffConfiguration), b.(*UpgradeDiffConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*UpgradeNodeConfiguration)(nil), (*kubeadm.UpgradeNodeConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta4_UpgradeNodeConfiguration_To_kubeadm_UpgradeNodeConfiguration(a.(*UpgradeNodeConfiguration), b.(*kubeadm.UpgradeNodeConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.UpgradeNodeConfiguration)(nil), (*UpgradeNodeConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_UpgradeNodeConfiguration_To_v1beta4_UpgradeNodeConfiguration(a.(*kubeadm.UpgradeNodeConfiguration), b.(*UpgradeNodeConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*UpgradePlanConfiguration)(nil), (*kubeadm.UpgradePlanConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta4_UpgradePlanConfiguration_To_kubeadm_UpgradePlanConfiguration(a.(*UpgradePlanConfiguration), b.(*kubeadm.UpgradePlanConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.UpgradePlanConfiguration)(nil), (*UpgradePlanConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_UpgradePlanConfiguration_To_v1beta4_UpgradePlanConfiguration(a.(*kubeadm.UpgradePlanConfiguration), b.(*UpgradePlanConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*kubeadm.APIServer)(nil), (*APIServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_APIServer_To_v1beta4_APIServer(a.(*kubeadm.APIServer), b.(*APIServer), scope)
|
||||
}); err != nil {
|
||||
@@ -940,3 +990,167 @@ func autoConvert_kubeadm_Timeouts_To_v1beta4_Timeouts(in *kubeadm.Timeouts, out
|
||||
func Convert_kubeadm_Timeouts_To_v1beta4_Timeouts(in *kubeadm.Timeouts, out *Timeouts, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Timeouts_To_v1beta4_Timeouts(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta4_UpgradeApplyConfiguration_To_kubeadm_UpgradeApplyConfiguration(in *UpgradeApplyConfiguration, out *kubeadm.UpgradeApplyConfiguration, s conversion.Scope) error {
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.AllowExperimentalUpgrades = (*bool)(unsafe.Pointer(in.AllowExperimentalUpgrades))
|
||||
out.AllowRCUpgrades = (*bool)(unsafe.Pointer(in.AllowRCUpgrades))
|
||||
out.CertificateRenewal = (*bool)(unsafe.Pointer(in.CertificateRenewal))
|
||||
out.DryRun = (*bool)(unsafe.Pointer(in.DryRun))
|
||||
out.EtcdUpgrade = (*bool)(unsafe.Pointer(in.EtcdUpgrade))
|
||||
out.ForceUpgrade = (*bool)(unsafe.Pointer(in.ForceUpgrade))
|
||||
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
|
||||
out.Patches = (*kubeadm.Patches)(unsafe.Pointer(in.Patches))
|
||||
out.PrintConfig = (*bool)(unsafe.Pointer(in.PrintConfig))
|
||||
out.SkipPhases = *(*[]string)(unsafe.Pointer(&in.SkipPhases))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta4_UpgradeApplyConfiguration_To_kubeadm_UpgradeApplyConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta4_UpgradeApplyConfiguration_To_kubeadm_UpgradeApplyConfiguration(in *UpgradeApplyConfiguration, out *kubeadm.UpgradeApplyConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta4_UpgradeApplyConfiguration_To_kubeadm_UpgradeApplyConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_UpgradeApplyConfiguration_To_v1beta4_UpgradeApplyConfiguration(in *kubeadm.UpgradeApplyConfiguration, out *UpgradeApplyConfiguration, s conversion.Scope) error {
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.AllowExperimentalUpgrades = (*bool)(unsafe.Pointer(in.AllowExperimentalUpgrades))
|
||||
out.AllowRCUpgrades = (*bool)(unsafe.Pointer(in.AllowRCUpgrades))
|
||||
out.CertificateRenewal = (*bool)(unsafe.Pointer(in.CertificateRenewal))
|
||||
out.DryRun = (*bool)(unsafe.Pointer(in.DryRun))
|
||||
out.EtcdUpgrade = (*bool)(unsafe.Pointer(in.EtcdUpgrade))
|
||||
out.ForceUpgrade = (*bool)(unsafe.Pointer(in.ForceUpgrade))
|
||||
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
|
||||
out.Patches = (*Patches)(unsafe.Pointer(in.Patches))
|
||||
out.PrintConfig = (*bool)(unsafe.Pointer(in.PrintConfig))
|
||||
out.SkipPhases = *(*[]string)(unsafe.Pointer(&in.SkipPhases))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_UpgradeApplyConfiguration_To_v1beta4_UpgradeApplyConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_UpgradeApplyConfiguration_To_v1beta4_UpgradeApplyConfiguration(in *kubeadm.UpgradeApplyConfiguration, out *UpgradeApplyConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_UpgradeApplyConfiguration_To_v1beta4_UpgradeApplyConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta4_UpgradeConfiguration_To_kubeadm_UpgradeConfiguration(in *UpgradeConfiguration, out *kubeadm.UpgradeConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1beta4_UpgradeApplyConfiguration_To_kubeadm_UpgradeApplyConfiguration(&in.Apply, &out.Apply, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta4_UpgradeDiffConfiguration_To_kubeadm_UpgradeDiffConfiguration(&in.Diff, &out.Diff, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta4_UpgradeNodeConfiguration_To_kubeadm_UpgradeNodeConfiguration(&in.Node, &out.Node, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta4_UpgradePlanConfiguration_To_kubeadm_UpgradePlanConfiguration(&in.Plan, &out.Plan, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta4_UpgradeConfiguration_To_kubeadm_UpgradeConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta4_UpgradeConfiguration_To_kubeadm_UpgradeConfiguration(in *UpgradeConfiguration, out *kubeadm.UpgradeConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta4_UpgradeConfiguration_To_kubeadm_UpgradeConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_UpgradeConfiguration_To_v1beta4_UpgradeConfiguration(in *kubeadm.UpgradeConfiguration, out *UpgradeConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_UpgradeApplyConfiguration_To_v1beta4_UpgradeApplyConfiguration(&in.Apply, &out.Apply, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_UpgradeDiffConfiguration_To_v1beta4_UpgradeDiffConfiguration(&in.Diff, &out.Diff, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_UpgradeNodeConfiguration_To_v1beta4_UpgradeNodeConfiguration(&in.Node, &out.Node, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_UpgradePlanConfiguration_To_v1beta4_UpgradePlanConfiguration(&in.Plan, &out.Plan, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_UpgradeConfiguration_To_v1beta4_UpgradeConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_UpgradeConfiguration_To_v1beta4_UpgradeConfiguration(in *kubeadm.UpgradeConfiguration, out *UpgradeConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_UpgradeConfiguration_To_v1beta4_UpgradeConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta4_UpgradeDiffConfiguration_To_kubeadm_UpgradeDiffConfiguration(in *UpgradeDiffConfiguration, out *kubeadm.UpgradeDiffConfiguration, s conversion.Scope) error {
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.DiffContextLines = in.DiffContextLines
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta4_UpgradeDiffConfiguration_To_kubeadm_UpgradeDiffConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta4_UpgradeDiffConfiguration_To_kubeadm_UpgradeDiffConfiguration(in *UpgradeDiffConfiguration, out *kubeadm.UpgradeDiffConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta4_UpgradeDiffConfiguration_To_kubeadm_UpgradeDiffConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_UpgradeDiffConfiguration_To_v1beta4_UpgradeDiffConfiguration(in *kubeadm.UpgradeDiffConfiguration, out *UpgradeDiffConfiguration, s conversion.Scope) error {
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.DiffContextLines = in.DiffContextLines
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_UpgradeDiffConfiguration_To_v1beta4_UpgradeDiffConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_UpgradeDiffConfiguration_To_v1beta4_UpgradeDiffConfiguration(in *kubeadm.UpgradeDiffConfiguration, out *UpgradeDiffConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_UpgradeDiffConfiguration_To_v1beta4_UpgradeDiffConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta4_UpgradeNodeConfiguration_To_kubeadm_UpgradeNodeConfiguration(in *UpgradeNodeConfiguration, out *kubeadm.UpgradeNodeConfiguration, s conversion.Scope) error {
|
||||
out.CertificateRenewal = (*bool)(unsafe.Pointer(in.CertificateRenewal))
|
||||
out.DryRun = (*bool)(unsafe.Pointer(in.DryRun))
|
||||
out.EtcdUpgrade = (*bool)(unsafe.Pointer(in.EtcdUpgrade))
|
||||
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
|
||||
out.SkipPhases = *(*[]string)(unsafe.Pointer(&in.SkipPhases))
|
||||
out.Patches = (*kubeadm.Patches)(unsafe.Pointer(in.Patches))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta4_UpgradeNodeConfiguration_To_kubeadm_UpgradeNodeConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta4_UpgradeNodeConfiguration_To_kubeadm_UpgradeNodeConfiguration(in *UpgradeNodeConfiguration, out *kubeadm.UpgradeNodeConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta4_UpgradeNodeConfiguration_To_kubeadm_UpgradeNodeConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_UpgradeNodeConfiguration_To_v1beta4_UpgradeNodeConfiguration(in *kubeadm.UpgradeNodeConfiguration, out *UpgradeNodeConfiguration, s conversion.Scope) error {
|
||||
out.CertificateRenewal = (*bool)(unsafe.Pointer(in.CertificateRenewal))
|
||||
out.DryRun = (*bool)(unsafe.Pointer(in.DryRun))
|
||||
out.EtcdUpgrade = (*bool)(unsafe.Pointer(in.EtcdUpgrade))
|
||||
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
|
||||
out.SkipPhases = *(*[]string)(unsafe.Pointer(&in.SkipPhases))
|
||||
out.Patches = (*Patches)(unsafe.Pointer(in.Patches))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_UpgradeNodeConfiguration_To_v1beta4_UpgradeNodeConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_UpgradeNodeConfiguration_To_v1beta4_UpgradeNodeConfiguration(in *kubeadm.UpgradeNodeConfiguration, out *UpgradeNodeConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_UpgradeNodeConfiguration_To_v1beta4_UpgradeNodeConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta4_UpgradePlanConfiguration_To_kubeadm_UpgradePlanConfiguration(in *UpgradePlanConfiguration, out *kubeadm.UpgradePlanConfiguration, s conversion.Scope) error {
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.AllowExperimentalUpgrades = (*bool)(unsafe.Pointer(in.AllowExperimentalUpgrades))
|
||||
out.AllowRCUpgrades = (*bool)(unsafe.Pointer(in.AllowRCUpgrades))
|
||||
out.DryRun = (*bool)(unsafe.Pointer(in.DryRun))
|
||||
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
|
||||
out.PrintConfig = (*bool)(unsafe.Pointer(in.PrintConfig))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta4_UpgradePlanConfiguration_To_kubeadm_UpgradePlanConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta4_UpgradePlanConfiguration_To_kubeadm_UpgradePlanConfiguration(in *UpgradePlanConfiguration, out *kubeadm.UpgradePlanConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta4_UpgradePlanConfiguration_To_kubeadm_UpgradePlanConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_UpgradePlanConfiguration_To_v1beta4_UpgradePlanConfiguration(in *kubeadm.UpgradePlanConfiguration, out *UpgradePlanConfiguration, s conversion.Scope) error {
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.AllowExperimentalUpgrades = (*bool)(unsafe.Pointer(in.AllowExperimentalUpgrades))
|
||||
out.AllowRCUpgrades = (*bool)(unsafe.Pointer(in.AllowRCUpgrades))
|
||||
out.DryRun = (*bool)(unsafe.Pointer(in.DryRun))
|
||||
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
|
||||
out.PrintConfig = (*bool)(unsafe.Pointer(in.PrintConfig))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_UpgradePlanConfiguration_To_v1beta4_UpgradePlanConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_UpgradePlanConfiguration_To_v1beta4_UpgradePlanConfiguration(in *kubeadm.UpgradePlanConfiguration, out *UpgradePlanConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_UpgradePlanConfiguration_To_v1beta4_UpgradePlanConfiguration(in, out, s)
|
||||
}
|
||||
|
@@ -658,3 +658,201 @@ func (in *Timeouts) DeepCopy() *Timeouts {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradeApplyConfiguration) DeepCopyInto(out *UpgradeApplyConfiguration) {
|
||||
*out = *in
|
||||
if in.AllowExperimentalUpgrades != nil {
|
||||
in, out := &in.AllowExperimentalUpgrades, &out.AllowExperimentalUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.AllowRCUpgrades != nil {
|
||||
in, out := &in.AllowRCUpgrades, &out.AllowRCUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.CertificateRenewal != nil {
|
||||
in, out := &in.CertificateRenewal, &out.CertificateRenewal
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.EtcdUpgrade != nil {
|
||||
in, out := &in.EtcdUpgrade, &out.EtcdUpgrade
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.ForceUpgrade != nil {
|
||||
in, out := &in.ForceUpgrade, &out.ForceUpgrade
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.IgnorePreflightErrors != nil {
|
||||
in, out := &in.IgnorePreflightErrors, &out.IgnorePreflightErrors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Patches != nil {
|
||||
in, out := &in.Patches, &out.Patches
|
||||
*out = new(Patches)
|
||||
**out = **in
|
||||
}
|
||||
if in.PrintConfig != nil {
|
||||
in, out := &in.PrintConfig, &out.PrintConfig
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.SkipPhases != nil {
|
||||
in, out := &in.SkipPhases, &out.SkipPhases
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeApplyConfiguration.
|
||||
func (in *UpgradeApplyConfiguration) DeepCopy() *UpgradeApplyConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeApplyConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradeConfiguration) DeepCopyInto(out *UpgradeConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.Apply.DeepCopyInto(&out.Apply)
|
||||
out.Diff = in.Diff
|
||||
in.Node.DeepCopyInto(&out.Node)
|
||||
in.Plan.DeepCopyInto(&out.Plan)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeConfiguration.
|
||||
func (in *UpgradeConfiguration) DeepCopy() *UpgradeConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *UpgradeConfiguration) 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.
|
||||
func (in *UpgradeDiffConfiguration) DeepCopyInto(out *UpgradeDiffConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeDiffConfiguration.
|
||||
func (in *UpgradeDiffConfiguration) DeepCopy() *UpgradeDiffConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeDiffConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradeNodeConfiguration) DeepCopyInto(out *UpgradeNodeConfiguration) {
|
||||
*out = *in
|
||||
if in.CertificateRenewal != nil {
|
||||
in, out := &in.CertificateRenewal, &out.CertificateRenewal
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.EtcdUpgrade != nil {
|
||||
in, out := &in.EtcdUpgrade, &out.EtcdUpgrade
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.IgnorePreflightErrors != nil {
|
||||
in, out := &in.IgnorePreflightErrors, &out.IgnorePreflightErrors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SkipPhases != nil {
|
||||
in, out := &in.SkipPhases, &out.SkipPhases
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Patches != nil {
|
||||
in, out := &in.Patches, &out.Patches
|
||||
*out = new(Patches)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeNodeConfiguration.
|
||||
func (in *UpgradeNodeConfiguration) DeepCopy() *UpgradeNodeConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeNodeConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradePlanConfiguration) DeepCopyInto(out *UpgradePlanConfiguration) {
|
||||
*out = *in
|
||||
if in.AllowExperimentalUpgrades != nil {
|
||||
in, out := &in.AllowExperimentalUpgrades, &out.AllowExperimentalUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.AllowRCUpgrades != nil {
|
||||
in, out := &in.AllowRCUpgrades, &out.AllowRCUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.IgnorePreflightErrors != nil {
|
||||
in, out := &in.IgnorePreflightErrors, &out.IgnorePreflightErrors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.PrintConfig != nil {
|
||||
in, out := &in.PrintConfig, &out.PrintConfig
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradePlanConfiguration.
|
||||
func (in *UpgradePlanConfiguration) DeepCopy() *UpgradePlanConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradePlanConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&InitConfiguration{}, func(obj interface{}) { SetObjectDefaults_InitConfiguration(obj.(*InitConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&ResetConfiguration{}, func(obj interface{}) { SetObjectDefaults_ResetConfiguration(obj.(*ResetConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&UpgradeConfiguration{}, func(obj interface{}) { SetObjectDefaults_UpgradeConfiguration(obj.(*UpgradeConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -87,3 +88,7 @@ func SetObjectDefaults_ResetConfiguration(in *ResetConfiguration) {
|
||||
SetDefaults_Timeouts(in.Timeouts)
|
||||
}
|
||||
}
|
||||
|
||||
func SetObjectDefaults_UpgradeConfiguration(in *UpgradeConfiguration) {
|
||||
SetDefaults_UpgradeConfiguration(in)
|
||||
}
|
||||
|
@@ -758,3 +758,12 @@ func ValidateImagePullPolicy(policy corev1.PullPolicy, fldPath *field.Path) fiel
|
||||
return allErrs
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateUpgradeConfiguration validates a UpgradeConfiguration object and collects all encountered errors
|
||||
func ValidateUpgradeConfiguration(c *kubeadm.UpgradeConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if c.Apply.Patches != nil {
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(c.Apply.Patches.Directory, field.NewPath("patches").Child("directory"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
@@ -744,11 +744,14 @@ func TestValidateMixedArguments(t *testing.T) {
|
||||
{[]string{"--foo=bar"}, true},
|
||||
{[]string{"--config=hello"}, true},
|
||||
{[]string{"--config=hello", "--ignore-preflight-errors=all"}, true},
|
||||
// Expected to succeed, --config is mixed with skip-* flags only or no other flags
|
||||
{[]string{"--config=hello", "--skip-token-print=true"}, true},
|
||||
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--skip-token-print"}, true},
|
||||
// Expected to fail, --config is mixed with the --foo flag
|
||||
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--foo=bar"}, false},
|
||||
{[]string{"--config=hello", "--foo=bar"}, false},
|
||||
// Expected to fail, --config is mixed with the upgrade related flag
|
||||
{[]string{"--config=hello", "--allow-experimental-upgrades"}, false},
|
||||
}
|
||||
|
||||
var cfgPath string
|
||||
@@ -760,6 +763,7 @@ func TestValidateMixedArguments(t *testing.T) {
|
||||
}
|
||||
f.String("foo", "", "flag bound to config object")
|
||||
f.StringSliceVar(&ignorePreflightErrors, "ignore-preflight-errors", ignorePreflightErrors, "flag not bound to config object")
|
||||
f.Bool("allow-experimental-upgrades", true, "upgrade flags for plan and apply command")
|
||||
f.Bool("skip-token-print", false, "flag not bound to config object")
|
||||
f.StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||
if err := f.Parse(rt.args); err != nil {
|
||||
|
198
cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go
generated
198
cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go
generated
@@ -698,3 +698,201 @@ func (in *Timeouts) DeepCopy() *Timeouts {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradeApplyConfiguration) DeepCopyInto(out *UpgradeApplyConfiguration) {
|
||||
*out = *in
|
||||
if in.AllowExperimentalUpgrades != nil {
|
||||
in, out := &in.AllowExperimentalUpgrades, &out.AllowExperimentalUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.AllowRCUpgrades != nil {
|
||||
in, out := &in.AllowRCUpgrades, &out.AllowRCUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.CertificateRenewal != nil {
|
||||
in, out := &in.CertificateRenewal, &out.CertificateRenewal
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.EtcdUpgrade != nil {
|
||||
in, out := &in.EtcdUpgrade, &out.EtcdUpgrade
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.ForceUpgrade != nil {
|
||||
in, out := &in.ForceUpgrade, &out.ForceUpgrade
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.IgnorePreflightErrors != nil {
|
||||
in, out := &in.IgnorePreflightErrors, &out.IgnorePreflightErrors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Patches != nil {
|
||||
in, out := &in.Patches, &out.Patches
|
||||
*out = new(Patches)
|
||||
**out = **in
|
||||
}
|
||||
if in.PrintConfig != nil {
|
||||
in, out := &in.PrintConfig, &out.PrintConfig
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.SkipPhases != nil {
|
||||
in, out := &in.SkipPhases, &out.SkipPhases
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeApplyConfiguration.
|
||||
func (in *UpgradeApplyConfiguration) DeepCopy() *UpgradeApplyConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeApplyConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradeConfiguration) DeepCopyInto(out *UpgradeConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.Apply.DeepCopyInto(&out.Apply)
|
||||
out.Diff = in.Diff
|
||||
in.Node.DeepCopyInto(&out.Node)
|
||||
in.Plan.DeepCopyInto(&out.Plan)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeConfiguration.
|
||||
func (in *UpgradeConfiguration) DeepCopy() *UpgradeConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *UpgradeConfiguration) 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.
|
||||
func (in *UpgradeDiffConfiguration) DeepCopyInto(out *UpgradeDiffConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeDiffConfiguration.
|
||||
func (in *UpgradeDiffConfiguration) DeepCopy() *UpgradeDiffConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeDiffConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradeNodeConfiguration) DeepCopyInto(out *UpgradeNodeConfiguration) {
|
||||
*out = *in
|
||||
if in.CertificateRenewal != nil {
|
||||
in, out := &in.CertificateRenewal, &out.CertificateRenewal
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.EtcdUpgrade != nil {
|
||||
in, out := &in.EtcdUpgrade, &out.EtcdUpgrade
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.IgnorePreflightErrors != nil {
|
||||
in, out := &in.IgnorePreflightErrors, &out.IgnorePreflightErrors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SkipPhases != nil {
|
||||
in, out := &in.SkipPhases, &out.SkipPhases
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Patches != nil {
|
||||
in, out := &in.Patches, &out.Patches
|
||||
*out = new(Patches)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradeNodeConfiguration.
|
||||
func (in *UpgradeNodeConfiguration) DeepCopy() *UpgradeNodeConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradeNodeConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpgradePlanConfiguration) DeepCopyInto(out *UpgradePlanConfiguration) {
|
||||
*out = *in
|
||||
if in.AllowExperimentalUpgrades != nil {
|
||||
in, out := &in.AllowExperimentalUpgrades, &out.AllowExperimentalUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.AllowRCUpgrades != nil {
|
||||
in, out := &in.AllowRCUpgrades, &out.AllowRCUpgrades
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.IgnorePreflightErrors != nil {
|
||||
in, out := &in.IgnorePreflightErrors, &out.IgnorePreflightErrors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.PrintConfig != nil {
|
||||
in, out := &in.PrintConfig, &out.PrintConfig
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpgradePlanConfiguration.
|
||||
func (in *UpgradePlanConfiguration) DeepCopy() *UpgradePlanConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpgradePlanConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
@@ -145,4 +145,13 @@ const (
|
||||
|
||||
// AllowExperimentalAPI flag can be used to allow experimental / work in progress APIs
|
||||
AllowExperimentalAPI = "allow-experimental-api"
|
||||
|
||||
// AllowRCUpgrades enable this flag will allow upgrading to a release candidate version of Kubernetes.
|
||||
AllowRCUpgrades = "allow-release-candidate-upgrades"
|
||||
|
||||
// AllowExperimentalUpgrades enable this flag will allow upgrading to an alpha/beta/release candidate version of Kubernetes.
|
||||
AllowExperimentalUpgrades = "allow-experimental-upgrades"
|
||||
|
||||
// PrintConfig specifies whether the cluster configuration that will be used in the upgrade should be printed or not.
|
||||
PrintConfig = "print-config"
|
||||
)
|
||||
|
@@ -60,7 +60,7 @@ func runControlPlane() func(c workflow.RunData) error {
|
||||
}
|
||||
|
||||
// otherwise, retrieve all the info required for control plane upgrade
|
||||
cfg := data.Cfg()
|
||||
cfg := data.InitCfg()
|
||||
client := data.Client()
|
||||
dryRun := data.DryRun()
|
||||
etcdUpgrade := data.EtcdUpgrade()
|
||||
|
@@ -31,7 +31,8 @@ type Data interface {
|
||||
EtcdUpgrade() bool
|
||||
RenewCerts() bool
|
||||
DryRun() bool
|
||||
Cfg() *kubeadmapi.InitConfiguration
|
||||
Cfg() *kubeadmapi.UpgradeConfiguration
|
||||
InitCfg() *kubeadmapi.InitConfiguration
|
||||
IsControlPlaneNode() bool
|
||||
Client() clientset.Interface
|
||||
IgnorePreflightErrors() sets.Set[string]
|
||||
|
@@ -34,7 +34,8 @@ var _ Data = &testData{}
|
||||
func (t *testData) EtcdUpgrade() bool { return false }
|
||||
func (t *testData) RenewCerts() bool { return false }
|
||||
func (t *testData) DryRun() bool { return false }
|
||||
func (t *testData) Cfg() *kubeadmapi.InitConfiguration { return nil }
|
||||
func (t *testData) Cfg() *kubeadmapi.UpgradeConfiguration { return nil }
|
||||
func (t *testData) InitCfg() *kubeadmapi.InitConfiguration { return nil }
|
||||
func (t *testData) IsControlPlaneNode() bool { return false }
|
||||
func (t *testData) Client() clientset.Interface { return nil }
|
||||
func (t *testData) IgnorePreflightErrors() sets.Set[string] { return nil }
|
||||
|
@@ -57,7 +57,7 @@ func runKubeletConfigPhase() func(c workflow.RunData) error {
|
||||
}
|
||||
|
||||
// otherwise, retrieve all the info required for kubelet config upgrade
|
||||
cfg := data.Cfg()
|
||||
cfg := data.InitCfg()
|
||||
dryRun := data.DryRun()
|
||||
|
||||
// Write the configuration for the kubelet down to disk and print the generated manifests instead if dry-running.
|
||||
|
@@ -60,7 +60,7 @@ func runPreflight(c workflow.RunData) error {
|
||||
fmt.Println("[preflight] Pulling images required for setting up a Kubernetes cluster")
|
||||
fmt.Println("[preflight] This might take a minute or two, depending on the speed of your internet connection")
|
||||
fmt.Println("[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'")
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), data.Cfg(), data.IgnorePreflightErrors()); err != nil {
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), data.InitCfg(), data.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
@@ -30,6 +31,7 @@ import (
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
@@ -71,7 +73,10 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
||||
DisableFlagsInUseLine: true,
|
||||
Short: "Upgrade your Kubernetes cluster to the specified version",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runApply(flags, args)
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return err
|
||||
}
|
||||
return runApply(cmd.Flags(), flags, args)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -81,7 +86,7 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
||||
cmd.Flags().BoolVarP(&flags.nonInteractiveMode, "yes", "y", flags.nonInteractiveMode, "Perform the upgrade and do not prompt for confirmation (non-interactive mode).")
|
||||
cmd.Flags().BoolVarP(&flags.force, "force", "f", flags.force, "Force upgrading although some requirements might not be met. This also implies non-interactive mode.")
|
||||
cmd.Flags().BoolVar(&flags.dryRun, options.DryRun, flags.dryRun, "Do not change any state, just output what actions would be performed.")
|
||||
cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.")
|
||||
cmd.Flags().BoolVar(&flags.etcdUpgrade, options.EtcdUpgrade, flags.etcdUpgrade, "Perform the upgrade of etcd.")
|
||||
cmd.Flags().BoolVar(&flags.renewCerts, options.CertificateRenewal, flags.renewCerts, "Perform the renewal of certificates used by component changed during upgrades.")
|
||||
options.AddPatchesFlag(cmd.Flags(), &flags.patchesDir)
|
||||
|
||||
@@ -100,39 +105,67 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
||||
// - Uploads the newly used configuration to the cluster ConfigMap
|
||||
// - Creating the RBAC rules for the bootstrap tokens and the cluster-info ConfigMap
|
||||
// - Applying new CoreDNS and kube-proxy manifests
|
||||
func runApply(flags *applyFlags, args []string) error {
|
||||
func runApply(flagSet *pflag.FlagSet, flags *applyFlags, args []string) error {
|
||||
|
||||
// Start with the basics, verify that the cluster is healthy and get the configuration from the cluster (using the ConfigMap)
|
||||
klog.V(1).Infoln("[upgrade/apply] verifying health of cluster")
|
||||
klog.V(1).Infoln("[upgrade/apply] retrieving configuration from cluster")
|
||||
client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, args, flags.dryRun, true, &output.TextPrinter{}, loadConfig)
|
||||
client, versionGetter, initCfg, upgradeCfg, err := enforceRequirements(flagSet, flags.applyPlanFlags, args, flags.dryRun, true, &output.TextPrinter{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate requested and validate actual version
|
||||
klog.V(1).Infoln("[upgrade/apply] validating requested and actual version")
|
||||
if err := configutil.NormalizeKubernetesVersion(&cfg.ClusterConfiguration); err != nil {
|
||||
if err := configutil.NormalizeKubernetesVersion(&initCfg.ClusterConfiguration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Use normalized version string in all following code.
|
||||
newK8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
||||
newK8sVersion, err := version.ParseSemantic(initCfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
return errors.Errorf("unable to parse normalized version %q as a semantic version", cfg.KubernetesVersion)
|
||||
return errors.Errorf("unable to parse normalized version %q as a semantic version", initCfg.KubernetesVersion)
|
||||
}
|
||||
|
||||
if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil {
|
||||
if err := features.ValidateVersion(features.InitFeatureGates, initCfg.FeatureGates, initCfg.KubernetesVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Enforce the version skew policies
|
||||
klog.V(1).Infoln("[upgrade/version] enforcing version skew policies")
|
||||
if err := EnforceVersionPolicies(cfg.KubernetesVersion, newK8sVersion, flags, versionGetter); err != nil {
|
||||
allowRCUpgrades, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.AllowRCUpgrades, upgradeCfg.Apply.AllowRCUpgrades, &flags.allowRCUpgrades).(*bool)
|
||||
if ok {
|
||||
flags.allowRCUpgrades = *allowRCUpgrades
|
||||
} else {
|
||||
return cmdutil.TypeMismatchErr("allowRCUpgrades", "bool")
|
||||
}
|
||||
|
||||
force, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, "force", upgradeCfg.Apply.ForceUpgrade, &flags.force).(*bool)
|
||||
if ok {
|
||||
flags.force = *force
|
||||
} else {
|
||||
return cmdutil.TypeMismatchErr("force", "bool")
|
||||
}
|
||||
|
||||
allowExperimentalUpgrades, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.AllowExperimentalUpgrades, upgradeCfg.Apply.AllowExperimentalUpgrades, &flags.allowExperimentalUpgrades).(*bool)
|
||||
if ok {
|
||||
flags.allowExperimentalUpgrades = *allowExperimentalUpgrades
|
||||
} else {
|
||||
return cmdutil.TypeMismatchErr("allowExperimentalUpgrades", "bool")
|
||||
}
|
||||
|
||||
if err := EnforceVersionPolicies(initCfg.KubernetesVersion, newK8sVersion, flags, versionGetter); err != nil {
|
||||
return errors.Wrap(err, "[upgrade/version] FATAL")
|
||||
}
|
||||
|
||||
// If the current session is interactive, ask the user whether they really want to upgrade.
|
||||
dryRun, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.DryRun, upgradeCfg.Apply.DryRun, &flags.dryRun).(*bool)
|
||||
if ok {
|
||||
flags.dryRun = *dryRun
|
||||
} else {
|
||||
return cmdutil.TypeMismatchErr("dryRun", "bool")
|
||||
}
|
||||
|
||||
if flags.sessionIsInteractive() {
|
||||
if err := cmdutil.InteractivelyConfirmAction("upgrade", "Are you sure you want to proceed?", os.Stdin); err != nil {
|
||||
return err
|
||||
@@ -143,7 +176,7 @@ func runApply(flags *applyFlags, args []string) error {
|
||||
fmt.Println("[upgrade/prepull] Pulling images required for setting up a Kubernetes cluster")
|
||||
fmt.Println("[upgrade/prepull] This might take a minute or two, depending on the speed of your internet connection")
|
||||
fmt.Println("[upgrade/prepull] You can also perform this action in beforehand using 'kubeadm config images pull'")
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), cfg, sets.New(cfg.NodeRegistration.IgnorePreflightErrors...)); err != nil {
|
||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), initCfg, sets.New(upgradeCfg.Apply.IgnorePreflightErrors...)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -152,14 +185,35 @@ func runApply(flags *applyFlags, args []string) error {
|
||||
|
||||
waiter := getWaiter(flags.dryRun, client, upgrade.UpgradeManifestTimeout)
|
||||
|
||||
// If the config is set by flag, just overwrite it!
|
||||
etcdUpgrade, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.EtcdUpgrade, upgradeCfg.Apply.EtcdUpgrade, &flags.etcdUpgrade).(*bool)
|
||||
if ok {
|
||||
upgradeCfg.Apply.EtcdUpgrade = etcdUpgrade
|
||||
} else {
|
||||
return cmdutil.TypeMismatchErr("etcdUpgrade", "bool")
|
||||
}
|
||||
|
||||
renewCerts, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.CertificateRenewal, upgradeCfg.Apply.CertificateRenewal, &flags.renewCerts).(*bool)
|
||||
if ok {
|
||||
upgradeCfg.Apply.CertificateRenewal = renewCerts
|
||||
} else {
|
||||
return cmdutil.TypeMismatchErr("renewCerts", "bool")
|
||||
}
|
||||
|
||||
if len(flags.patchesDir) > 0 {
|
||||
upgradeCfg.Apply.Patches = &kubeadmapi.Patches{Directory: flags.patchesDir}
|
||||
} else if upgradeCfg.Apply.Patches == nil {
|
||||
upgradeCfg.Apply.Patches = &kubeadmapi.Patches{}
|
||||
}
|
||||
|
||||
// Now; perform the upgrade procedure
|
||||
if err := PerformControlPlaneUpgrade(flags, client, waiter, cfg); err != nil {
|
||||
if err := PerformControlPlaneUpgrade(flags, client, waiter, initCfg, upgradeCfg); err != nil {
|
||||
return errors.Wrap(err, "[upgrade/apply] FATAL")
|
||||
}
|
||||
|
||||
// Upgrade RBAC rules and addons.
|
||||
klog.V(1).Infoln("[upgrade/postupgrade] upgrading RBAC rules and addons")
|
||||
if err := upgrade.PerformPostUpgradeTasks(client, cfg, flags.patchesDir, flags.dryRun, flags.applyPlanFlags.out); err != nil {
|
||||
if err := upgrade.PerformPostUpgradeTasks(client, initCfg, upgradeCfg.Apply.Patches.Directory, flags.dryRun, flags.applyPlanFlags.out); err != nil {
|
||||
return errors.Wrap(err, "[upgrade/postupgrade] FATAL post-upgrade error")
|
||||
}
|
||||
|
||||
@@ -169,7 +223,7 @@ func runApply(flags *applyFlags, args []string) error {
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
fmt.Printf("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", cfg.KubernetesVersion)
|
||||
fmt.Printf("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", initCfg.KubernetesVersion)
|
||||
fmt.Println("")
|
||||
fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.")
|
||||
|
||||
@@ -203,15 +257,14 @@ func EnforceVersionPolicies(newK8sVersionStr string, newK8sVersion *version.Vers
|
||||
}
|
||||
|
||||
// PerformControlPlaneUpgrade actually performs the upgrade procedure for the cluster of your type (self-hosted or static-pod-hosted)
|
||||
func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.InitConfiguration) error {
|
||||
|
||||
func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, waiter apiclient.Waiter, initCfg *kubeadmapi.InitConfiguration, upgradeCfg *kubeadmapi.UpgradeConfiguration) error {
|
||||
// OK, the cluster is hosted using static pods. Upgrade a static-pod hosted cluster
|
||||
fmt.Printf("[upgrade/apply] Upgrading your Static Pod-hosted control plane to version %q (timeout: %v)...\n",
|
||||
internalcfg.KubernetesVersion, upgrade.UpgradeManifestTimeout)
|
||||
initCfg.KubernetesVersion, upgrade.UpgradeManifestTimeout)
|
||||
|
||||
if flags.dryRun {
|
||||
return upgrade.DryRunStaticPodUpgrade(flags.patchesDir, internalcfg)
|
||||
return upgrade.DryRunStaticPodUpgrade(upgradeCfg.Apply.Patches.Directory, initCfg)
|
||||
}
|
||||
|
||||
return upgrade.PerformStaticPodUpgrade(client, waiter, internalcfg, flags.etcdUpgrade, flags.renewCerts, flags.patchesDir)
|
||||
return upgrade.PerformStaticPodUpgrade(client, waiter, initCfg, *upgradeCfg.Apply.EtcdUpgrade, *upgradeCfg.Apply.CertificateRenewal, upgradeCfg.Apply.Patches.Directory)
|
||||
}
|
||||
|
@@ -24,21 +24,25 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||
@@ -46,162 +50,121 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
)
|
||||
|
||||
// isKubeadmConfigPresent checks if a kubeadm config type is found in the provided document map
|
||||
func isKubeadmConfigPresent(docmap kubeadmapi.DocumentMap) bool {
|
||||
for gvk := range docmap {
|
||||
if gvk.Group == kubeadmapi.GroupName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// loadConfig loads configuration from a file and/or the cluster. InitConfiguration, ClusterConfiguration and (optionally) component configs
|
||||
// are loaded. This function allows the component configs to be loaded from a file that contains only them. If the file contains any kubeadm types
|
||||
// in it (API group "kubeadm.k8s.io" present), then the supplied file is treaded as a legacy reconfiguration style "--config" use and the
|
||||
// returned bool value is set to true (the only case to be done so).
|
||||
func loadConfig(cfgPath string, client clientset.Interface, skipComponentConfigs bool, printer output.Printer) (*kubeadmapi.InitConfiguration, bool, error) {
|
||||
// Used for info logs here
|
||||
const logPrefix = "upgrade/config"
|
||||
|
||||
// The usual case here is to not have a config file, but rather load the config from the cluster.
|
||||
// This is probably 90% of the time. So we handle it first.
|
||||
if cfgPath == "" {
|
||||
cfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, false, skipComponentConfigs)
|
||||
return cfg, false, err
|
||||
}
|
||||
|
||||
// Otherwise, we have a config file. Let's load it.
|
||||
configBytes, err := os.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrapf(err, "unable to load config from file %q", cfgPath)
|
||||
}
|
||||
|
||||
// Split the YAML documents in the file into a DocumentMap
|
||||
docmap, err := kubeadmutil.SplitYAMLDocuments(configBytes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// If there are kubeadm types (API group kubeadm.k8s.io) present, we need to keep the existing behavior
|
||||
// here. Basically, we have to load all of the configs from the file and none from the cluster. Configs that are
|
||||
// missing from the file will be automatically regenerated by kubeadm even if they are present in the cluster.
|
||||
// The resulting configs overwrite the existing cluster ones at the end of a successful upgrade apply operation.
|
||||
if isKubeadmConfigPresent(docmap) {
|
||||
klog.Warning("WARNING: Usage of the --config flag with kubeadm config types for reconfiguring the cluster during upgrade is not recommended!")
|
||||
cfg, err := configutil.BytesToInitConfiguration(configBytes, false)
|
||||
return cfg, true, err
|
||||
}
|
||||
|
||||
// If no kubeadm config types are present, we assume that there are manually upgraded component configs in the file.
|
||||
// Hence, we load the kubeadm types from the cluster.
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, false, true)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Stop here if the caller does not want us to load the component configs
|
||||
if !skipComponentConfigs {
|
||||
// Load the component configs with upgrades
|
||||
if err := componentconfigs.FetchFromClusterWithLocalOverwrites(&initCfg.ClusterConfiguration, client, docmap); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Now default and validate the configs
|
||||
componentconfigs.Default(&initCfg.ClusterConfiguration, &initCfg.LocalAPIEndpoint, &initCfg.NodeRegistration)
|
||||
if errs := componentconfigs.Validate(&initCfg.ClusterConfiguration); len(errs) != 0 {
|
||||
return nil, false, errs.ToAggregate()
|
||||
}
|
||||
}
|
||||
|
||||
return initCfg, false, nil
|
||||
}
|
||||
|
||||
// LoadConfigFunc is a function type that loads configuration from a file and/or the cluster.
|
||||
type LoadConfigFunc func(cfgPath string, client clientset.Interface, skipComponentConfigs bool, printer output.Printer) (*kubeadmapi.InitConfiguration, bool, error)
|
||||
|
||||
// enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure
|
||||
func enforceRequirements(flags *applyPlanFlags, args []string, dryRun bool, upgradeApply bool, printer output.Printer, loadConfig LoadConfigFunc) (clientset.Interface, upgrade.VersionGetter, *kubeadmapi.InitConfiguration, error) {
|
||||
client, err := getClient(flags.kubeConfigPath, dryRun)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
|
||||
}
|
||||
|
||||
func enforceRequirements(flagSet *pflag.FlagSet, flags *applyPlanFlags, args []string, dryRun bool, upgradeApply bool, printer output.Printer) (clientset.Interface, upgrade.VersionGetter, *kubeadmapi.InitConfiguration, *kubeadmapi.UpgradeConfiguration, error) {
|
||||
// Fetch the configuration from a file or ConfigMap and validate it
|
||||
_, _ = printer.Println("[upgrade/config] Loading the kubeadm configuration")
|
||||
_, _ = printer.Printf("[upgrade/config] Making sure the configuration is correct:\n")
|
||||
|
||||
var newK8sVersion string
|
||||
cfg, legacyReconfigure, err := loadConfig(flags.cfgPath, client, !upgradeApply, printer)
|
||||
upgradeCfg, err := configutil.LoadUpgradeConfig(flags.cfgPath)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "could not load the kubeadm configuration")
|
||||
} else if legacyReconfigure {
|
||||
// Set the newK8sVersion to the value in the ClusterConfiguration. This is done, so that users who use the --config option
|
||||
// to supply a new ClusterConfiguration don't have to specify the Kubernetes version twice,
|
||||
// if they don't want to upgrade but just change a setting.
|
||||
newK8sVersion = cfg.KubernetesVersion
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/upgrade config] FATAL")
|
||||
}
|
||||
|
||||
// The version arg is mandatory, during upgrade apply, unless it's specified in the config file
|
||||
if upgradeApply && newK8sVersion == "" {
|
||||
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
||||
return nil, nil, nil, err
|
||||
// `dryRun` should be always `false` for `kubeadm plan`.
|
||||
isDryRun := ptr.To(false)
|
||||
printConfigCfg := upgradeCfg.Plan.PrintConfig
|
||||
ignoreErrCfg := upgradeCfg.Plan.IgnorePreflightErrors
|
||||
ok := false
|
||||
if upgradeApply {
|
||||
printConfigCfg = upgradeCfg.Apply.PrintConfig
|
||||
ignoreErrCfg = upgradeCfg.Apply.IgnorePreflightErrors
|
||||
isDryRun, ok = cmdutil.ValueFromFlagsOrConfig(flagSet, options.DryRun, upgradeCfg.Apply.DryRun, &dryRun).(*bool)
|
||||
if !ok {
|
||||
return nil, nil, nil, nil, cmdutil.TypeMismatchErr("dryRun", "bool")
|
||||
}
|
||||
}
|
||||
|
||||
client, err := getClient(flags.kubeConfigPath, *isDryRun)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
|
||||
}
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, ignoreErrCfg)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
// Also set the union of pre-flight errors to UpgradeConfiguration, to provide a consistent view of the runtime configuration.
|
||||
// .Plan.IgnorePreflightErrors is not set as it's not used.
|
||||
if upgradeApply {
|
||||
upgradeCfg.Apply.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
||||
}
|
||||
|
||||
// Ensure the user is root
|
||||
klog.V(1).Info("running preflight checks")
|
||||
if err := runPreflightChecks(client, ignorePreflightErrorsSet, printer); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, "upgrade/config", false, true)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, _ = printer.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %s namespace must exist.\n", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
|
||||
_, _ = printer.Printf("[upgrade/config] Next steps:\n")
|
||||
_, _ = printer.Printf("\t- OPTION 1: Run 'kubeadm config upload from-flags' and specify the same CLI arguments you passed to 'kubeadm init' when you created your control-plane.\n")
|
||||
_, _ = printer.Printf("\t- OPTION 2: Run 'kubeadm config upload from-file' and specify the same config file you passed to 'kubeadm init' when you created your control-plane.\n")
|
||||
_, _ = printer.Println()
|
||||
err = errors.Errorf("the ConfigMap %q in the %s namespace used for getting configuration information was not found", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
|
||||
}
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/init config] FATAL")
|
||||
}
|
||||
|
||||
newK8sVersion := upgradeCfg.Plan.KubernetesVersion
|
||||
if upgradeApply {
|
||||
newK8sVersion = upgradeCfg.Apply.KubernetesVersion
|
||||
// The version arg is mandatory, during upgrade apply, unless it's specified in the config file
|
||||
if newK8sVersion == "" {
|
||||
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If option was specified in both args and config file, args will overwrite the config file.
|
||||
if len(args) == 1 {
|
||||
newK8sVersion = args[0]
|
||||
if upgradeApply {
|
||||
// The `upgrade apply` version always overwrites the KubernetesVersion in the returned cfg with the target
|
||||
// version. While this is not the same for `upgrade plan` where the KubernetesVersion should be the old
|
||||
// one (because the call to getComponentConfigVersionStates requires the currently installed version).
|
||||
// This also makes the KubernetesVersion value returned for `upgrade plan` consistent as that command
|
||||
// allows to not specify a target version in which case KubernetesVersion will always hold the currently
|
||||
// installed one.
|
||||
cfg.KubernetesVersion = newK8sVersion
|
||||
}
|
||||
}
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
// Also set the union of pre-flight errors to InitConfiguration, to provide a consistent view of the runtime configuration:
|
||||
cfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
||||
|
||||
// Ensure the user is root
|
||||
klog.V(1).Info("running preflight checks")
|
||||
if err := runPreflightChecks(client, ignorePreflightErrorsSet, printer); err != nil {
|
||||
return nil, nil, nil, err
|
||||
if upgradeApply {
|
||||
// The `upgrade apply` version always overwrites the KubernetesVersion in the returned cfg with the target
|
||||
// version. While this is not the same for `upgrade plan` where the KubernetesVersion should be the old
|
||||
// one (because the call to getComponentConfigVersionStates requires the currently installed version).
|
||||
// This also makes the KubernetesVersion value returned for `upgrade plan` consistent as that command
|
||||
// allows to not specify a target version in which case KubernetesVersion will always hold the currently
|
||||
// installed one.
|
||||
initCfg.KubernetesVersion = newK8sVersion
|
||||
}
|
||||
|
||||
// Run healthchecks against the cluster
|
||||
if err := upgrade.CheckClusterHealth(client, &cfg.ClusterConfiguration, ignorePreflightErrorsSet, printer); err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "[upgrade/health] FATAL")
|
||||
if err := upgrade.CheckClusterHealth(client, &initCfg.ClusterConfiguration, ignorePreflightErrorsSet, printer); err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/health] FATAL")
|
||||
}
|
||||
|
||||
// If features gates are passed to the command line, use it (otherwise use featureGates from configuration)
|
||||
if flags.featureGatesString != "" {
|
||||
cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString)
|
||||
initCfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "[upgrade/config] FATAL")
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/config] FATAL")
|
||||
}
|
||||
}
|
||||
|
||||
// Check if feature gate flags used in the cluster are consistent with the set of features currently supported by kubeadm
|
||||
if msg := features.CheckDeprecatedFlags(&features.InitFeatureGates, cfg.FeatureGates); len(msg) > 0 {
|
||||
if msg := features.CheckDeprecatedFlags(&features.InitFeatureGates, initCfg.FeatureGates); len(msg) > 0 {
|
||||
for _, m := range msg {
|
||||
printer.Printf("[upgrade/config] %s\n", m)
|
||||
}
|
||||
}
|
||||
|
||||
// If the user told us to print this information out; do it!
|
||||
if flags.printConfig {
|
||||
printConfiguration(&cfg.ClusterConfiguration, os.Stdout, printer)
|
||||
printConfig, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.PrintConfig, printConfigCfg, &flags.printConfig).(*bool)
|
||||
if ok && *printConfig {
|
||||
printConfiguration(&initCfg.ClusterConfiguration, os.Stdout, printer)
|
||||
} else if !ok {
|
||||
return nil, nil, nil, nil, cmdutil.TypeMismatchErr("printConfig", "bool")
|
||||
}
|
||||
|
||||
// Use a real version getter interface that queries the API server, the kubeadm client and the Kubernetes CI system for latest versions
|
||||
return client, upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(client), newK8sVersion), cfg, nil
|
||||
return client, upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(client), newK8sVersion), initCfg, upgradeCfg, nil
|
||||
}
|
||||
|
||||
// printConfiguration prints the external version of the API to yaml
|
||||
|
@@ -24,7 +24,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
@@ -53,25 +54,18 @@ users:
|
||||
client-certificate-data:
|
||||
`
|
||||
|
||||
func fakeLoadConfig(cfgPath string, client clientset.Interface, skipComponentConfigs bool, printer output.Printer) (*kubeadmapi.InitConfiguration, bool, error) {
|
||||
return &kubeadmapi.InitConfiguration{}, false, nil
|
||||
}
|
||||
|
||||
func TestEnforceRequirements(t *testing.T) {
|
||||
tmpDir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
fullPath := filepath.Join(tmpDir, "test-config-file")
|
||||
f, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create test file %q: %v", fullPath, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = f.WriteString(testConfigToken); err != nil {
|
||||
t.Errorf("Unable to write test file %q: %v", fullPath, err)
|
||||
}
|
||||
|
||||
tcases := []struct {
|
||||
name string
|
||||
newK8sVersion string
|
||||
@@ -106,8 +100,7 @@ func TestEnforceRequirements(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tcases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, _, _, err := enforceRequirements(&tt.flags, nil, tt.dryRun, false, &output.TextPrinter{}, fakeLoadConfig)
|
||||
|
||||
_, _, _, _, err := enforceRequirements(&pflag.FlagSet{}, &tt.flags, nil, tt.dryRun, false, &output.TextPrinter{})
|
||||
if err == nil && len(tt.expectedErr) != 0 {
|
||||
t.Error("Expected error, but got success")
|
||||
}
|
||||
@@ -123,7 +116,6 @@ func TestEnforceRequirements(t *testing.T) {
|
||||
if err != nil && !strings.Contains(err.Error(), expErr) {
|
||||
t.Fatalf("enforceRequirements returned unexpected error, expected: %s, got %v", expErr, err)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -212,52 +204,3 @@ func TestPrintConfiguration(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsKubeadmConfigPresent(t *testing.T) {
|
||||
var tcases = []struct {
|
||||
name string
|
||||
gvkmap kubeadmapi.DocumentMap
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: " Wrong Group value",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"}: []byte(`kind: Foo`),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Empty Group value",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: "", Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Nil value",
|
||||
gvkmap: nil,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Correct Group value 1",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: "kubeadm.k8s.io", Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Correct Group value 2",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: kubeadmapi.GroupName, Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tcases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if isKubeadmConfigPresent(tt.gvkmap) != tt.expected {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -23,13 +23,15 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
@@ -37,6 +39,7 @@ import (
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
)
|
||||
|
||||
type diffFlags struct {
|
||||
@@ -74,7 +77,11 @@ func newCmdDiff(out io.Writer) *cobra.Command {
|
||||
flags.schedulerManifestPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return runDiff(flags, args)
|
||||
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return err
|
||||
}
|
||||
return runDiff(cmd.Flags(), flags, args, configutil.FetchInitConfigurationFromCluster)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -107,50 +114,49 @@ func validateManifestsPath(manifests ...string) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDiff(flags *diffFlags, args []string) error {
|
||||
var err error
|
||||
var cfg *kubeadmapi.InitConfiguration
|
||||
if flags.cfgPath != "" {
|
||||
cfg, err = configutil.LoadInitConfigurationFromFile(flags.cfgPath, configutil.LoadOrDefaultConfigurationOptions{
|
||||
SkipCRIDetect: true,
|
||||
})
|
||||
} else {
|
||||
var client client.Interface
|
||||
client, err = kubeconfigutil.ClientSetFromFile(flags.kubeConfigPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
|
||||
}
|
||||
cfg, err = configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade/diff", false, false)
|
||||
// FetchInitConfigurationFunc defines the signature of the function which will fetch InitConfiguration from cluster.
|
||||
type FetchInitConfigurationFunc func(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error)
|
||||
|
||||
func runDiff(fs *pflag.FlagSet, flags *diffFlags, args []string, fetchInitConfigurationFromCluster FetchInitConfigurationFunc) error {
|
||||
upgradeCfg, err := configutil.LoadUpgradeConfig(flags.cfgPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := kubeconfigutil.ClientSetFromFile(flags.kubeConfigPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
|
||||
}
|
||||
initCfg, err := fetchInitConfigurationFromCluster(client, &output.TextPrinter{}, "upgrade/diff", false, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the version is specified in config file, pick up that value.
|
||||
if cfg.KubernetesVersion != "" {
|
||||
flags.newK8sVersionStr = cfg.KubernetesVersion
|
||||
// Pick up the version from the ClusterConfiguration.
|
||||
if initCfg.KubernetesVersion != "" {
|
||||
flags.newK8sVersionStr = initCfg.KubernetesVersion
|
||||
}
|
||||
if upgradeCfg.Diff.KubernetesVersion != "" {
|
||||
flags.newK8sVersionStr = upgradeCfg.Diff.KubernetesVersion
|
||||
}
|
||||
|
||||
// If the new version is already specified in config file, version arg is optional.
|
||||
// Version must be specified via version arg if it's not set in ClusterConfiguration.
|
||||
if flags.newK8sVersionStr == "" {
|
||||
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If option was specified in both args and config file, args will overwrite the config file.
|
||||
if len(args) == 1 {
|
||||
flags.newK8sVersionStr = args[0]
|
||||
}
|
||||
|
||||
_, err = version.ParseSemantic(flags.newK8sVersionStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.ClusterConfiguration.KubernetesVersion = flags.newK8sVersionStr
|
||||
initCfg.ClusterConfiguration.KubernetesVersion = flags.newK8sVersionStr
|
||||
|
||||
specs := controlplane.GetStaticPodSpecs(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, nil)
|
||||
specs := controlplane.GetStaticPodSpecs(&initCfg.ClusterConfiguration, &initCfg.LocalAPIEndpoint, nil)
|
||||
for spec, pod := range specs {
|
||||
var path string
|
||||
switch spec {
|
||||
@@ -164,7 +170,6 @@ func runDiff(flags *diffFlags, args []string) error {
|
||||
klog.Errorf("[diff] unknown spec %v", spec)
|
||||
continue
|
||||
}
|
||||
|
||||
newManifest, err := kubeadmutil.MarshalToYaml(&pod, corev1.SchemeGroupVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -183,7 +188,7 @@ func runDiff(flags *diffFlags, args []string) error {
|
||||
B: difflib.SplitLines(string(newManifest)),
|
||||
FromFile: path,
|
||||
ToFile: "new manifest",
|
||||
Context: flags.contextLines,
|
||||
Context: cmdutil.ValueFromFlagsOrConfig(fs, "context-lines", upgradeCfg.Diff.DiffContextLines, flags.contextLines).(int),
|
||||
}
|
||||
|
||||
difflib.WriteUnifiedDiff(flags.out, diff)
|
||||
|
@@ -24,8 +24,10 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
)
|
||||
|
||||
func createTestRunDiffFile(contents []byte) (string, error) {
|
||||
@@ -42,23 +44,25 @@ func createTestRunDiffFile(contents []byte) (string, error) {
|
||||
return file.Name(), nil
|
||||
}
|
||||
|
||||
func TestRunDiff(t *testing.T) {
|
||||
currentVersion := "v" + constants.CurrentKubernetesVersion.String()
|
||||
func fakeFetchInitConfig(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
return &kubeadmapi.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
|
||||
KubernetesVersion: "v1.0.1",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestRunDiff(t *testing.T) {
|
||||
// create a temporary file with valid ClusterConfiguration
|
||||
testUpgradeDiffConfigContents := []byte(fmt.Sprintf(`
|
||||
apiVersion: %s
|
||||
kind: InitConfiguration
|
||||
---
|
||||
apiVersion: %[1]s
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: %s`, kubeadmapiv1.SchemeGroupVersion.String(), currentVersion))
|
||||
kind: UpgradeConfiguration
|
||||
contextLines: 4`, kubeadmapiv1.SchemeGroupVersion.String()))
|
||||
testUpgradeDiffConfig, err := createTestRunDiffFile(testUpgradeDiffConfigContents)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(testUpgradeDiffConfig)
|
||||
|
||||
// create a temporary manifest file with dummy contents
|
||||
testUpgradeDiffManifestContents := []byte("some-contents")
|
||||
testUpgradeDiffManifest, err := createTestRunDiffFile(testUpgradeDiffManifestContents)
|
||||
@@ -67,6 +71,13 @@ kubernetesVersion: %s`, kubeadmapiv1.SchemeGroupVersion.String(), currentVersion
|
||||
}
|
||||
defer os.Remove(testUpgradeDiffManifest)
|
||||
|
||||
kubeConfigPath, err := createTestRunDiffFile([]byte(testConfigToken))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
//nolint:errcheck
|
||||
defer os.Remove(kubeConfigPath)
|
||||
|
||||
flags := &diffFlags{
|
||||
cfgPath: "",
|
||||
out: io.Discard,
|
||||
@@ -118,12 +129,14 @@ kubernetesVersion: %s`, kubeadmapiv1.SchemeGroupVersion.String(), currentVersion
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
flags.cfgPath = tc.cfgPath
|
||||
flags.kubeConfigPath = kubeConfigPath
|
||||
cmd := newCmdDiff(os.Stdout)
|
||||
if tc.setManifestPath {
|
||||
flags.apiServerManifestPath = tc.manifestPath
|
||||
flags.controllerManagerManifestPath = tc.manifestPath
|
||||
flags.schedulerManifestPath = tc.manifestPath
|
||||
}
|
||||
if err := runDiff(flags, tc.args); (err != nil) != tc.expectedError {
|
||||
if err := runDiff(cmd.Flags(), flags, tc.args, fakeFetchInitConfig); (err != nil) != tc.expectedError {
|
||||
t.Fatalf("expected error: %v, saw: %v, error: %v", tc.expectedError, (err != nil), err)
|
||||
}
|
||||
})
|
||||
|
@@ -32,6 +32,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
)
|
||||
@@ -40,6 +41,7 @@ import (
|
||||
// Please note that this structure includes the public kubeadm config API, but only a subset of the options
|
||||
// supported by this api will be exposed as a flag.
|
||||
type nodeOptions struct {
|
||||
cfgPath string
|
||||
kubeConfigPath string
|
||||
etcdUpgrade bool
|
||||
renewCerts bool
|
||||
@@ -57,7 +59,8 @@ type nodeData struct {
|
||||
etcdUpgrade bool
|
||||
renewCerts bool
|
||||
dryRun bool
|
||||
cfg *kubeadmapi.InitConfiguration
|
||||
cfg *kubeadmapi.UpgradeConfiguration
|
||||
initCfg *kubeadmapi.InitConfiguration
|
||||
isControlPlaneNode bool
|
||||
client clientset.Interface
|
||||
patchesDir string
|
||||
@@ -75,6 +78,10 @@ func newCmdNode(out io.Writer) *cobra.Command {
|
||||
Use: "node",
|
||||
Short: "Upgrade commands for a node in the cluster",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nodeRunner.Run(args)
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
@@ -83,6 +90,7 @@ func newCmdNode(out io.Writer) *cobra.Command {
|
||||
// adds flags to the node command
|
||||
// flags could be eventually inherited by the sub-commands automatically generated for phases
|
||||
addUpgradeNodeFlags(cmd.Flags(), nodeOptions)
|
||||
options.AddConfigFlag(cmd.Flags(), &nodeOptions.cfgPath)
|
||||
options.AddPatchesFlag(cmd.Flags(), &nodeOptions.patchesDir)
|
||||
|
||||
// initialize the workflow runner with the list of phases
|
||||
@@ -93,7 +101,15 @@ func newCmdNode(out io.Writer) *cobra.Command {
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
nodeRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (workflow.RunData, error) {
|
||||
return newNodeData(cmd, args, nodeOptions, out)
|
||||
data, err := newNodeData(cmd, args, nodeOptions, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If the flag for skipping phases was empty, use the values from config
|
||||
if len(nodeRunner.Options.SkipPhases) == 0 {
|
||||
nodeRunner.Options.SkipPhases = data.cfg.Node.SkipPhases
|
||||
}
|
||||
return data, nil
|
||||
})
|
||||
|
||||
// binds the Runner to kubeadm upgrade node command by altering
|
||||
@@ -124,50 +140,69 @@ func addUpgradeNodeFlags(flagSet *flag.FlagSet, nodeOptions *nodeOptions) {
|
||||
// newNodeData returns a new nodeData struct to be used for the execution of the kubeadm upgrade node workflow.
|
||||
// This func takes care of validating nodeOptions passed to the command, and then it converts
|
||||
// options into the internal InitConfiguration type that is used as input all the phases in the kubeadm upgrade node workflow
|
||||
func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions, out io.Writer) (*nodeData, error) {
|
||||
func newNodeData(cmd *cobra.Command, args []string, nodeOptions *nodeOptions, out io.Writer) (*nodeData, error) {
|
||||
// Checks if a node is a control-plane node by looking up the kube-apiserver manifest file
|
||||
isControlPlaneNode := true
|
||||
filepath := constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory())
|
||||
if _, err := os.Stat(filepath); os.IsNotExist(err) {
|
||||
isControlPlaneNode = false
|
||||
}
|
||||
if len(options.kubeConfigPath) == 0 {
|
||||
if len(nodeOptions.kubeConfigPath) == 0 {
|
||||
// Update the kubeconfig path depending on whether this is a control plane node or not.
|
||||
options.kubeConfigPath = constants.GetKubeletKubeConfigPath()
|
||||
nodeOptions.kubeConfigPath = constants.GetKubeletKubeConfigPath()
|
||||
if isControlPlaneNode {
|
||||
options.kubeConfigPath = constants.GetAdminKubeConfigPath()
|
||||
nodeOptions.kubeConfigPath = constants.GetAdminKubeConfigPath()
|
||||
}
|
||||
}
|
||||
|
||||
client, err := getClient(options.kubeConfigPath, options.dryRun)
|
||||
upgradeCfg, err := configutil.LoadUpgradeConfig(nodeOptions.cfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", options.kubeConfigPath)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dryRun, ok := cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.DryRun, upgradeCfg.Node.DryRun, &nodeOptions.dryRun).(*bool)
|
||||
if !ok {
|
||||
return nil, cmdutil.TypeMismatchErr("dryRun", "bool")
|
||||
}
|
||||
client, err := getClient(nodeOptions.kubeConfigPath, *dryRun)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", nodeOptions.kubeConfigPath)
|
||||
}
|
||||
|
||||
// Fetches the cluster configuration
|
||||
// NB in case of control-plane node, we are reading all the info for the node; in case of NOT control-plane node
|
||||
// (worker node), we are not reading local API address and the CRI socket from the node object
|
||||
cfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", !isControlPlaneNode, false)
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", !isControlPlaneNode, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||
}
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(nodeOptions.ignorePreflightErrors, initCfg.NodeRegistration.IgnorePreflightErrors)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Also set the union of pre-flight errors to JoinConfiguration, to provide a consistent view of the runtime configuration:
|
||||
cfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
||||
initCfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
||||
|
||||
var patchesDir string
|
||||
if upgradeCfg.Node.Patches != nil {
|
||||
patchesDir = cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.Patches, upgradeCfg.Node.Patches.Directory, nodeOptions.patchesDir).(string)
|
||||
} else {
|
||||
patchesDir = nodeOptions.patchesDir
|
||||
}
|
||||
|
||||
return &nodeData{
|
||||
etcdUpgrade: options.etcdUpgrade,
|
||||
renewCerts: options.renewCerts,
|
||||
dryRun: options.dryRun,
|
||||
cfg: cfg,
|
||||
cfg: upgradeCfg,
|
||||
dryRun: *dryRun,
|
||||
initCfg: initCfg,
|
||||
client: client,
|
||||
isControlPlaneNode: isControlPlaneNode,
|
||||
patchesDir: options.patchesDir,
|
||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||
kubeConfigPath: options.kubeConfigPath,
|
||||
kubeConfigPath: nodeOptions.kubeConfigPath,
|
||||
outputWriter: out,
|
||||
patchesDir: patchesDir,
|
||||
etcdUpgrade: *cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.EtcdUpgrade, upgradeCfg.Node.EtcdUpgrade, &nodeOptions.etcdUpgrade).(*bool),
|
||||
renewCerts: *cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.CertificateRenewal, upgradeCfg.Node.CertificateRenewal, &nodeOptions.renewCerts).(*bool),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -186,11 +221,16 @@ func (d *nodeData) RenewCerts() bool {
|
||||
return d.renewCerts
|
||||
}
|
||||
|
||||
// Cfg returns initConfiguration.
|
||||
func (d *nodeData) Cfg() *kubeadmapi.InitConfiguration {
|
||||
// Cfg returns upgradeConfiguration.
|
||||
func (d *nodeData) Cfg() *kubeadmapi.UpgradeConfiguration {
|
||||
return d.cfg
|
||||
}
|
||||
|
||||
// InitCfg returns the InitConfiguration.
|
||||
func (d *nodeData) InitCfg() *kubeadmapi.InitConfiguration {
|
||||
return d.initCfg
|
||||
}
|
||||
|
||||
// IsControlPlaneNode returns the isControlPlaneNode flag.
|
||||
func (d *nodeData) IsControlPlaneNode() bool {
|
||||
return d.isControlPlaneNode
|
||||
|
@@ -27,14 +27,17 @@ import (
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
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/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
@@ -64,13 +67,16 @@ func newCmdPlan(apf *applyPlanFlags) *cobra.Command {
|
||||
Use: "plan [version] [flags]",
|
||||
Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable.",
|
||||
Long: upgradePlanLongDesc,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
printer, err := outputFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not construct output printer")
|
||||
}
|
||||
|
||||
return runPlan(flags, args, printer)
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return err
|
||||
}
|
||||
return runPlan(cmd.Flags(), flags, args, printer)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -91,29 +97,41 @@ func newComponentUpgradePlan(name, currentVersion, newVersion string) outputapiv
|
||||
}
|
||||
|
||||
// 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(flagSet *pflag.FlagSet, 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.
|
||||
klog.V(1).Infoln("[upgrade/plan] verifying health of cluster")
|
||||
klog.V(1).Infoln("[upgrade/plan] retrieving configuration from cluster")
|
||||
client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, args, false, false, printer, loadConfig)
|
||||
client, versionGetter, initCfg, upgradeCfg, err := enforceRequirements(flagSet, flags.applyPlanFlags, args, false, false, printer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Currently this is the only method we have for distinguishing
|
||||
// external etcd vs static pod etcd
|
||||
isExternalEtcd := cfg.Etcd.External != nil
|
||||
isExternalEtcd := initCfg.Etcd.External != nil
|
||||
|
||||
// Compute which upgrade possibilities there are
|
||||
klog.V(1).Infoln("[upgrade/plan] computing upgrade possibilities")
|
||||
availUpgrades, err := upgrade.GetAvailableUpgrades(versionGetter, flags.allowExperimentalUpgrades, flags.allowRCUpgrades, isExternalEtcd, client, constants.GetStaticPodDirectory(), printer)
|
||||
|
||||
// flags are respected while keeping the configuration file not changed.
|
||||
allowRCUpgrades, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.AllowRCUpgrades, upgradeCfg.Plan.AllowRCUpgrades, &flags.allowRCUpgrades).(*bool)
|
||||
if !ok {
|
||||
return cmdutil.TypeMismatchErr("allowRCUpgrades", "bool")
|
||||
}
|
||||
|
||||
allowExperimentalUpgrades, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.AllowExperimentalUpgrades, upgradeCfg.Plan.AllowExperimentalUpgrades, &flags.allowExperimentalUpgrades).(*bool)
|
||||
if !ok {
|
||||
return cmdutil.TypeMismatchErr("allowExperimentalUpgrades", "bool")
|
||||
}
|
||||
|
||||
availUpgrades, err := upgrade.GetAvailableUpgrades(versionGetter, *allowExperimentalUpgrades, *allowRCUpgrades, isExternalEtcd, client, constants.GetStaticPodDirectory(), printer)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "[upgrade/versions] FATAL")
|
||||
}
|
||||
|
||||
// Fetch the current state of the component configs
|
||||
klog.V(1).Infoln("[upgrade/plan] analysing component config version states")
|
||||
configVersionStates, err := componentconfigs.GetVersionStates(&cfg.ClusterConfiguration, client)
|
||||
configVersionStates, err := componentconfigs.GetVersionStates(&initCfg.ClusterConfiguration, client)
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "[upgrade/versions] FATAL")
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ import (
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
@@ -135,6 +136,18 @@ func ValueFromFlagsOrConfig(flagSet *pflag.FlagSet, name string, cfgValue interf
|
||||
if flagSet.Changed(name) {
|
||||
return flagValue
|
||||
}
|
||||
|
||||
// covert the nil to false if this is a bool, this will help to get rid of nil dereference error.
|
||||
cfg, ok := cfgValue.(*bool)
|
||||
if ok && cfg == nil {
|
||||
return ptr.To(false)
|
||||
}
|
||||
|
||||
// assume config has all the defaults set correctly.
|
||||
return cfgValue
|
||||
}
|
||||
|
||||
// TypeMismatchErr return an error which indicates how the type is mismatched.
|
||||
func TypeMismatchErr(opt, rType string) error {
|
||||
return errors.Errorf("type mismatch, %s is expected to be a pointer to %s", opt, rType)
|
||||
}
|
||||
|
@@ -128,6 +128,12 @@ func TestValueFromFlagsOrConfig(t *testing.T) {
|
||||
flagValue: false,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "nil bool is converted to false",
|
||||
cfg: (*bool)(nil),
|
||||
flagValue: false,
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
type options struct {
|
||||
@@ -140,11 +146,15 @@ func TestValueFromFlagsOrConfig(t *testing.T) {
|
||||
fs.BoolVar(&fakeOptions.bar, "bar", false, "")
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := fs.Set(tt.flag, fmt.Sprintf("%v", tt.flagValue))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to set the value of the flag %v", tt.flagValue)
|
||||
if tt.flag != "" {
|
||||
if err := fs.Set(tt.flag, fmt.Sprintf("%v", tt.flagValue)); err != nil {
|
||||
t.Fatalf("failed to set the value of the flag %v", tt.flagValue)
|
||||
}
|
||||
}
|
||||
actualResult := ValueFromFlagsOrConfig(&fs, tt.flag, tt.cfg, tt.flagValue)
|
||||
if result, ok := actualResult.(*bool); ok {
|
||||
actualResult = *result
|
||||
}
|
||||
if actualResult != tt.expected {
|
||||
t.Errorf(
|
||||
"failed ValueFromFlagsOrConfig:\n\texpected: %s\n\t actual: %s",
|
||||
|
@@ -452,6 +452,8 @@ const (
|
||||
EtcdUserName string = "kubeadm-etcd"
|
||||
// ServiceAccountKeyReadersGroupName is the group of users that are allowed to read the service account private key.
|
||||
ServiceAccountKeyReadersGroupName string = "kubeadm-sa-key-readers"
|
||||
// UpgradeConfigurationKind is the string kind value for the UpgradeConfiguration struct
|
||||
UpgradeConfigurationKind = "UpgradeConfiguration"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package config contains utilities for managing the kubeadm configuration API.
|
||||
package config
|
||||
|
||||
import (
|
||||
@@ -490,3 +491,13 @@ func defaultEmptyMigrateMutators() migrateMutators {
|
||||
|
||||
return *mutators
|
||||
}
|
||||
|
||||
// isKubeadmConfigPresent checks if a kubeadm config type is found in the provided document map
|
||||
func isKubeadmConfigPresent(docmap kubeadmapi.DocumentMap) bool {
|
||||
for gvk := range docmap {
|
||||
if gvk.Group == kubeadmapi.GroupName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@@ -858,3 +858,52 @@ func TestDefaultMigrateMutators(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsKubeadmConfigPresent(t *testing.T) {
|
||||
var tcases = []struct {
|
||||
name string
|
||||
gvkmap kubeadmapi.DocumentMap
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: " Wrong Group value",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"}: []byte(`kind: Foo`),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Empty Group value",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: "", Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Nil value",
|
||||
gvkmap: nil,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Correct Group value 1",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: "kubeadm.k8s.io", Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Correct Group value 2",
|
||||
gvkmap: kubeadmapi.DocumentMap{
|
||||
{Group: kubeadmapi.GroupName, Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tcases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if isKubeadmConfigPresent(tt.gvkmap) != tt.expected {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
158
cmd/kubeadm/app/util/config/upgradeconfiguration.go
Normal file
158
cmd/kubeadm/app/util/config/upgradeconfiguration.go
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/klog/v2"
|
||||
kubeproxyconfig "k8s.io/kube-proxy/config/v1alpha1"
|
||||
kubeletconfig "k8s.io/kubelet/config/v1beta1"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict"
|
||||
)
|
||||
|
||||
var componentCfgGV = sets.New(kubeproxyconfig.GroupName, kubeletconfig.GroupName)
|
||||
|
||||
// DefaultUpgradeConfiguration return a default UpgradeConfiguration
|
||||
func DefaultUpgradeConfiguration() (*kubeadmapi.UpgradeConfiguration, error) {
|
||||
versionedCfg := &kubeadmapiv1.UpgradeConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(versionedCfg)
|
||||
cfg := &kubeadmapi.UpgradeConfiguration{}
|
||||
if err := kubeadmscheme.Scheme.Convert(versionedCfg, cfg, nil); err != nil {
|
||||
return nil, errors.Wrap(err, "could not prepare a defaulted UpgradeConfiguration")
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// documentMapToUpgradeConfiguration takes a map between GVKs and YAML documents (as returned by SplitYAMLDocuments),
|
||||
// finds a UpgradeConfiguration, decodes it, dynamically defaults it and then validates it prior to return.
|
||||
func documentMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated bool) (*kubeadmapi.UpgradeConfiguration, error) {
|
||||
var internalcfg *kubeadmapi.UpgradeConfiguration
|
||||
|
||||
for gvk, bytes := range gvkmap {
|
||||
// check if this version is supported and possibly not deprecated
|
||||
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify the validity of the YAML
|
||||
if err := strict.VerifyUnmarshalStrict([]*runtime.Scheme{kubeadmscheme.Scheme}, gvk, bytes); err != nil {
|
||||
klog.Warning(err.Error())
|
||||
}
|
||||
|
||||
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvk) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvk) {
|
||||
klog.Warningf("[config] WARNING: YAML document with GroupVersionKind %v is deprecated for upgrade, please use config file with kind of UpgradeConfiguration instead \n", gvk)
|
||||
continue
|
||||
}
|
||||
|
||||
if kubeadmutil.GroupVersionKindsHasUpgradeConfiguration(gvk) {
|
||||
// Set internalcfg to an empty struct value the deserializer will populate
|
||||
internalcfg = &kubeadmapi.UpgradeConfiguration{}
|
||||
// Decode the bytes into the internal struct. Under the hood, the bytes will be unmarshalled into the
|
||||
// right external version, defaulted, and converted into the internal version.
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), bytes, internalcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// If the group is neither a kubeadm core type or of a supported component config group, we dump a warning about it being ignored
|
||||
if !componentconfigs.Scheme.IsGroupRegistered(gvk.Group) {
|
||||
klog.Warningf("[config] WARNING: Ignored YAML document with GroupVersionKind %v\n", gvk)
|
||||
}
|
||||
}
|
||||
|
||||
// If UpgradeConfiguration wasn't given, default it by creating an external struct instance, default it and convert into the internal type
|
||||
if internalcfg == nil {
|
||||
extinitcfg := &kubeadmapiv1.UpgradeConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(extinitcfg)
|
||||
// Set upgradeCfg to an empty struct value the deserializer will populate
|
||||
internalcfg = &kubeadmapi.UpgradeConfiguration{}
|
||||
if err := kubeadmscheme.Scheme.Convert(extinitcfg, internalcfg, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Validates cfg
|
||||
if err := validation.ValidateUpgradeConfiguration(internalcfg).ToAggregate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return internalcfg, nil
|
||||
}
|
||||
|
||||
// DocMapToUpgradeConfiguration converts documentMap to an internal, defaulted and validated UpgradeConfiguration object.
|
||||
// The map may contain many different YAML documents. These YAML documents are parsed one-by-one
|
||||
// and well-known ComponentConfig GroupVersionKinds are stored inside of the internal UpgradeConfiguration struct.
|
||||
// The resulting UpgradeConfiguration is then dynamically defaulted and validated prior to return.
|
||||
func DocMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap) (*kubeadmapi.UpgradeConfiguration, error) {
|
||||
return documentMapToUpgradeConfiguration(gvkmap, false)
|
||||
}
|
||||
|
||||
// LoadUpgradeConfig loads UpgradeConfiguration from a file.
|
||||
func LoadUpgradeConfig(cfgPath string) (*kubeadmapi.UpgradeConfiguration, error) {
|
||||
var err error
|
||||
var upgradeCfg *kubeadmapi.UpgradeConfiguration
|
||||
if cfgPath == "" {
|
||||
if upgradeCfg, err = DefaultUpgradeConfiguration(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return upgradeCfg, nil
|
||||
}
|
||||
|
||||
// Otherwise, we have a config file. Let's load it.
|
||||
configBytes, err := os.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to load config from file %q", cfgPath)
|
||||
}
|
||||
|
||||
// Split the YAML documents in the file into a DocumentMap
|
||||
docmap, err := kubeadmutil.SplitYAMLDocuments(configBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert documentMap to internal UpgradeConfiguration, InitConfiguration and ClusterConfiguration from config file will be ignored.
|
||||
// Upgrade should respect the cluster configuration from the existing cluster, re-configure the cluster with a InitConfiguration and
|
||||
// ClusterConfiguration from the config file is not allowed for upgrade.
|
||||
if isKubeadmConfigPresent(docmap) {
|
||||
if upgradeCfg, err = DocMapToUpgradeConfiguration(docmap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check is there any component configs defined in the config file.
|
||||
for gvk := range docmap {
|
||||
if componentCfgGV.Has(gvk.Group) {
|
||||
klog.Warningf("[config] WARNING: YAML document with Component Configs %v is deprecated for upgrade and will be ignored \n", gvk.Group)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return upgradeCfg, nil
|
||||
}
|
104
cmd/kubeadm/app/util/config/upgradeconfiguration_test.go
Normal file
104
cmd/kubeadm/app/util/config/upgradeconfiguration_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
func TestDocMapToUpgradeConfiguration(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg kubeadmapiv1.UpgradeConfiguration
|
||||
expectedCfg kubeadmapi.UpgradeConfiguration
|
||||
}{
|
||||
{
|
||||
name: "default config is set correctly",
|
||||
cfg: kubeadmapiv1.UpgradeConfiguration{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: kubeadmapiv1.SchemeGroupVersion.String(),
|
||||
Kind: constants.UpgradeConfigurationKind,
|
||||
},
|
||||
},
|
||||
expectedCfg: kubeadmapi.UpgradeConfiguration{
|
||||
Apply: kubeadmapi.UpgradeApplyConfiguration{
|
||||
CertificateRenewal: ptr.To(true),
|
||||
EtcdUpgrade: ptr.To(true),
|
||||
},
|
||||
Node: kubeadmapi.UpgradeNodeConfiguration{
|
||||
CertificateRenewal: ptr.To(true),
|
||||
EtcdUpgrade: ptr.To(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cfg has part of fields configured",
|
||||
cfg: kubeadmapiv1.UpgradeConfiguration{
|
||||
Apply: kubeadmapiv1.UpgradeApplyConfiguration{
|
||||
CertificateRenewal: ptr.To(false),
|
||||
},
|
||||
Node: kubeadmapiv1.UpgradeNodeConfiguration{
|
||||
EtcdUpgrade: ptr.To(false),
|
||||
},
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: kubeadmapiv1.SchemeGroupVersion.String(),
|
||||
Kind: constants.UpgradeConfigurationKind,
|
||||
},
|
||||
},
|
||||
expectedCfg: kubeadmapi.UpgradeConfiguration{
|
||||
Apply: kubeadmapi.UpgradeApplyConfiguration{
|
||||
CertificateRenewal: ptr.To(false),
|
||||
EtcdUpgrade: ptr.To(true),
|
||||
},
|
||||
Node: kubeadmapi.UpgradeNodeConfiguration{
|
||||
CertificateRenewal: ptr.To(true),
|
||||
EtcdUpgrade: ptr.To(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
b, err := yaml.Marshal(tc.cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while marshalling to YAML: %v", err)
|
||||
}
|
||||
docmap, err := kubeadmutil.SplitYAMLDocuments(b)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpect error of SplitYAMLDocuments: %v", err)
|
||||
}
|
||||
cfg, err := DocMapToUpgradeConfiguration(docmap)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error of DocMapToUpgradeConfiguration: %v\nconfig: %s", err, string(b))
|
||||
}
|
||||
if diff := cmp.Diff(*cfg, tc.expectedCfg); diff != "" {
|
||||
t.Fatalf("DocMapToUpgradeConfiguration returned unexpected diff (-want,+got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -151,3 +151,8 @@ func GroupVersionKindsHasJoinConfiguration(gvks ...schema.GroupVersionKind) bool
|
||||
func GroupVersionKindsHasResetConfiguration(gvks ...schema.GroupVersionKind) bool {
|
||||
return GroupVersionKindsHasKind(gvks, constants.ResetConfigurationKind)
|
||||
}
|
||||
|
||||
// GroupVersionKindsHasUpgradeConfiguration returns whether the following gvk slice contains a UpgradeConfiguration object
|
||||
func GroupVersionKindsHasUpgradeConfiguration(gvks ...schema.GroupVersionKind) bool {
|
||||
return GroupVersionKindsHasKind(gvks, constants.UpgradeConfigurationKind)
|
||||
}
|
||||
|
@@ -431,3 +431,69 @@ func TestGroupVersionKindsHasResetConfiguration(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupVersionKindsHasClusterConfiguration(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
gvks []schema.GroupVersionKind
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "does not have ClusterConfiguraiton",
|
||||
gvks: []schema.GroupVersionKind{
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "has ClusterConfiguraiton",
|
||||
gvks: []schema.GroupVersionKind{
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"},
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "ClusterConfiguration"},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
actual := GroupVersionKindsHasClusterConfiguration(rt.gvks...)
|
||||
if rt.expected != actual {
|
||||
t.Errorf("expected gvks to have a ClusterConfiguration: %t\n\tactual: %t\n", rt.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupVersionKindsHasUpgradeConfiguration(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
gvks []schema.GroupVersionKind
|
||||
kind string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "no UpgradeConfiguration found",
|
||||
gvks: []schema.GroupVersionKind{
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "UpgradeConfiguration is found",
|
||||
gvks: []schema.GroupVersionKind{
|
||||
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"},
|
||||
{Group: "bar.k8s.io", Version: "v2", Kind: "UpgradeConfiguration"},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
actual := GroupVersionKindsHasUpgradeConfiguration(rt.gvks...)
|
||||
if rt.expected != actual {
|
||||
t2.Errorf("expected gvks has UpgradeConfiguration: %t\n\tactual: %t\n", rt.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user