kubeadm: implementation of API types
Signed-off-by: calvin <wen.chen@daocloud.io> Co-authored-by: Dave Chen <dave.chen@arm.com>
This commit is contained in:
@@ -41,6 +41,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||||||
fuzzJoinConfiguration,
|
fuzzJoinConfiguration,
|
||||||
fuzzJoinControlPlane,
|
fuzzJoinControlPlane,
|
||||||
fuzzResetConfiguration,
|
fuzzResetConfiguration,
|
||||||
|
fuzzUpgradeConfiguration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,3 +153,13 @@ func fuzzResetConfiguration(obj *kubeadm.ResetConfiguration, c fuzz.Continue) {
|
|||||||
obj.CertificatesDir = "/tmp"
|
obj.CertificatesDir = "/tmp"
|
||||||
kubeadm.SetDefaultTimeouts(&obj.Timeouts)
|
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{},
|
&ClusterConfiguration{},
|
||||||
&JoinConfiguration{},
|
&JoinConfiguration{},
|
||||||
&ResetConfiguration{},
|
&ResetConfiguration{},
|
||||||
|
&UpgradeConfiguration{},
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ type InitConfiguration struct {
|
|||||||
// the `json:"-"` tag in the external variant of these API types.
|
// the `json:"-"` tag in the external variant of these API types.
|
||||||
ClusterConfiguration `json:"-"`
|
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
|
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.
|
// 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"
|
// 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 {
|
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.
|
// 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.
|
// Defaults to the hostname of the node if not provided.
|
||||||
Name string
|
Name string
|
||||||
@@ -541,6 +541,125 @@ type ResetConfiguration struct {
|
|||||||
Timeouts *Timeouts
|
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 (
|
const (
|
||||||
// UnmountFlagMNTForce represents the flag "MNT_FORCE"
|
// UnmountFlagMNTForce represents the flag "MNT_FORCE"
|
||||||
UnmountFlagMNTForce = "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.
|
// that can be used to configure various timeouts.
|
||||||
// - Add the `NodeRegistration.ImagePullSerial` field in 'InitConfiguration` and `JoinConfiguration`, which
|
// - Add the `NodeRegistration.ImagePullSerial` field in 'InitConfiguration` and `JoinConfiguration`, which
|
||||||
// can be used to control if kubeadm pulls images serially or in parallel.
|
// 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
|
// Migration from old kubeadm config versions
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||||||
&ClusterConfiguration{},
|
&ClusterConfiguration{},
|
||||||
&JoinConfiguration{},
|
&JoinConfiguration{},
|
||||||
&ResetConfiguration{},
|
&ResetConfiguration{},
|
||||||
|
&UpgradeConfiguration{},
|
||||||
)
|
)
|
||||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -597,3 +597,151 @@ type Timeouts struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Discovery *metav1.Duration `json:"discovery,omitempty"`
|
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 {
|
}); err != nil {
|
||||||
return err
|
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 {
|
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)
|
return Convert_kubeadm_APIServer_To_v1beta4_APIServer(a.(*kubeadm.APIServer), b.(*APIServer), scope)
|
||||||
}); err != nil {
|
}); 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 {
|
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)
|
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)
|
in.DeepCopyInto(out)
|
||||||
return 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(&InitConfiguration{}, func(obj interface{}) { SetObjectDefaults_InitConfiguration(obj.(*InitConfiguration)) })
|
||||||
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
|
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
|
||||||
scheme.AddTypeDefaultingFunc(&ResetConfiguration{}, func(obj interface{}) { SetObjectDefaults_ResetConfiguration(obj.(*ResetConfiguration)) })
|
scheme.AddTypeDefaultingFunc(&ResetConfiguration{}, func(obj interface{}) { SetObjectDefaults_ResetConfiguration(obj.(*ResetConfiguration)) })
|
||||||
|
scheme.AddTypeDefaultingFunc(&UpgradeConfiguration{}, func(obj interface{}) { SetObjectDefaults_UpgradeConfiguration(obj.(*UpgradeConfiguration)) })
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,3 +88,7 @@ func SetObjectDefaults_ResetConfiguration(in *ResetConfiguration) {
|
|||||||
SetDefaults_Timeouts(in.Timeouts)
|
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
|
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{"--foo=bar"}, true},
|
||||||
{[]string{"--config=hello"}, true},
|
{[]string{"--config=hello"}, true},
|
||||||
{[]string{"--config=hello", "--ignore-preflight-errors=all"}, 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", "--skip-token-print=true"}, true},
|
||||||
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--skip-token-print"}, true},
|
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--skip-token-print"}, true},
|
||||||
// Expected to fail, --config is mixed with the --foo flag
|
// Expected to fail, --config is mixed with the --foo flag
|
||||||
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--foo=bar"}, false},
|
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--foo=bar"}, false},
|
||||||
{[]string{"--config=hello", "--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
|
var cfgPath string
|
||||||
@@ -760,6 +763,7 @@ func TestValidateMixedArguments(t *testing.T) {
|
|||||||
}
|
}
|
||||||
f.String("foo", "", "flag bound to config object")
|
f.String("foo", "", "flag bound to config object")
|
||||||
f.StringSliceVar(&ignorePreflightErrors, "ignore-preflight-errors", ignorePreflightErrors, "flag not 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.Bool("skip-token-print", false, "flag not bound to config object")
|
||||||
f.StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
f.StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||||
if err := f.Parse(rt.args); err != nil {
|
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)
|
in.DeepCopyInto(out)
|
||||||
return 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 flag can be used to allow experimental / work in progress APIs
|
||||||
AllowExperimentalAPI = "allow-experimental-api"
|
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
|
// otherwise, retrieve all the info required for control plane upgrade
|
||||||
cfg := data.Cfg()
|
cfg := data.InitCfg()
|
||||||
client := data.Client()
|
client := data.Client()
|
||||||
dryRun := data.DryRun()
|
dryRun := data.DryRun()
|
||||||
etcdUpgrade := data.EtcdUpgrade()
|
etcdUpgrade := data.EtcdUpgrade()
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ type Data interface {
|
|||||||
EtcdUpgrade() bool
|
EtcdUpgrade() bool
|
||||||
RenewCerts() bool
|
RenewCerts() bool
|
||||||
DryRun() bool
|
DryRun() bool
|
||||||
Cfg() *kubeadmapi.InitConfiguration
|
Cfg() *kubeadmapi.UpgradeConfiguration
|
||||||
|
InitCfg() *kubeadmapi.InitConfiguration
|
||||||
IsControlPlaneNode() bool
|
IsControlPlaneNode() bool
|
||||||
Client() clientset.Interface
|
Client() clientset.Interface
|
||||||
IgnorePreflightErrors() sets.Set[string]
|
IgnorePreflightErrors() sets.Set[string]
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ var _ Data = &testData{}
|
|||||||
func (t *testData) EtcdUpgrade() bool { return false }
|
func (t *testData) EtcdUpgrade() bool { return false }
|
||||||
func (t *testData) RenewCerts() bool { return false }
|
func (t *testData) RenewCerts() bool { return false }
|
||||||
func (t *testData) DryRun() 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) IsControlPlaneNode() bool { return false }
|
||||||
func (t *testData) Client() clientset.Interface { return nil }
|
func (t *testData) Client() clientset.Interface { return nil }
|
||||||
func (t *testData) IgnorePreflightErrors() sets.Set[string] { 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
|
// otherwise, retrieve all the info required for kubelet config upgrade
|
||||||
cfg := data.Cfg()
|
cfg := data.InitCfg()
|
||||||
dryRun := data.DryRun()
|
dryRun := data.DryRun()
|
||||||
|
|
||||||
// Write the configuration for the kubelet down to disk and print the generated manifests instead if dry-running.
|
// 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] 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] 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'")
|
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
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
@@ -30,6 +31,7 @@ import (
|
|||||||
utilsexec "k8s.io/utils/exec"
|
utilsexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
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"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||||
@@ -71,7 +73,10 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Short: "Upgrade your Kubernetes cluster to the specified version",
|
Short: "Upgrade your Kubernetes cluster to the specified version",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
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.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().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.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.")
|
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)
|
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
|
// - Uploads the newly used configuration to the cluster ConfigMap
|
||||||
// - Creating the RBAC rules for the bootstrap tokens and the cluster-info ConfigMap
|
// - Creating the RBAC rules for the bootstrap tokens and the cluster-info ConfigMap
|
||||||
// - Applying new CoreDNS and kube-proxy manifests
|
// - 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)
|
// 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] verifying health of cluster")
|
||||||
klog.V(1).Infoln("[upgrade/apply] retrieving configuration from 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate requested and validate actual version
|
// Validate requested and validate actual version
|
||||||
klog.V(1).Infoln("[upgrade/apply] validating requested and 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use normalized version string in all following code.
|
// Use normalized version string in all following code.
|
||||||
newK8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
newK8sVersion, err := version.ParseSemantic(initCfg.KubernetesVersion)
|
||||||
if err != nil {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce the version skew policies
|
// Enforce the version skew policies
|
||||||
klog.V(1).Infoln("[upgrade/version] enforcing 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")
|
return errors.Wrap(err, "[upgrade/version] FATAL")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current session is interactive, ask the user whether they really want to upgrade.
|
// 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 flags.sessionIsInteractive() {
|
||||||
if err := cmdutil.InteractivelyConfirmAction("upgrade", "Are you sure you want to proceed?", os.Stdin); err != nil {
|
if err := cmdutil.InteractivelyConfirmAction("upgrade", "Are you sure you want to proceed?", os.Stdin); err != nil {
|
||||||
return err
|
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] 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] 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'")
|
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
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -152,14 +185,35 @@ func runApply(flags *applyFlags, args []string) error {
|
|||||||
|
|
||||||
waiter := getWaiter(flags.dryRun, client, upgrade.UpgradeManifestTimeout)
|
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
|
// 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")
|
return errors.Wrap(err, "[upgrade/apply] FATAL")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade RBAC rules and addons.
|
// Upgrade RBAC rules and addons.
|
||||||
klog.V(1).Infoln("[upgrade/postupgrade] upgrading 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")
|
return errors.Wrap(err, "[upgrade/postupgrade] FATAL post-upgrade error")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +223,7 @@ func runApply(flags *applyFlags, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("")
|
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("")
|
||||||
fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.")
|
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)
|
// 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
|
// 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",
|
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 {
|
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"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"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"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
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/apis/kubeadm/validation"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||||
@@ -46,162 +50,121 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
"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
|
// 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) {
|
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) {
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the configuration from a file or ConfigMap and validate it
|
// 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
|
upgradeCfg, err := configutil.LoadUpgradeConfig(flags.cfgPath)
|
||||||
cfg, legacyReconfigure, err := loadConfig(flags.cfgPath, client, !upgradeApply, printer)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, errors.Wrap(err, "could not load the kubeadm configuration")
|
return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/upgrade config] FATAL")
|
||||||
} 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The version arg is mandatory, during upgrade apply, unless it's specified in the config file
|
// `dryRun` should be always `false` for `kubeadm plan`.
|
||||||
if upgradeApply && newK8sVersion == "" {
|
isDryRun := ptr.To(false)
|
||||||
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
printConfigCfg := upgradeCfg.Plan.PrintConfig
|
||||||
return nil, nil, nil, err
|
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 option was specified in both args and config file, args will overwrite the config file.
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
newK8sVersion = args[0]
|
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 upgradeApply {
|
||||||
if err != nil {
|
// The `upgrade apply` version always overwrites the KubernetesVersion in the returned cfg with the target
|
||||||
return nil, nil, nil, err
|
// 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).
|
||||||
// Also set the union of pre-flight errors to InitConfiguration, to provide a consistent view of the runtime configuration:
|
// This also makes the KubernetesVersion value returned for `upgrade plan` consistent as that command
|
||||||
cfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
// allows to not specify a target version in which case KubernetesVersion will always hold the currently
|
||||||
|
// installed one.
|
||||||
// Ensure the user is root
|
initCfg.KubernetesVersion = newK8sVersion
|
||||||
klog.V(1).Info("running preflight checks")
|
|
||||||
if err := runPreflightChecks(client, ignorePreflightErrorsSet, printer); err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run healthchecks against the cluster
|
// Run healthchecks against the cluster
|
||||||
if err := upgrade.CheckClusterHealth(client, &cfg.ClusterConfiguration, ignorePreflightErrorsSet, printer); err != nil {
|
if err := upgrade.CheckClusterHealth(client, &initCfg.ClusterConfiguration, ignorePreflightErrorsSet, printer); err != nil {
|
||||||
return nil, nil, nil, errors.Wrap(err, "[upgrade/health] FATAL")
|
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 features gates are passed to the command line, use it (otherwise use featureGates from configuration)
|
||||||
if flags.featureGatesString != "" {
|
if flags.featureGatesString != "" {
|
||||||
cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString)
|
initCfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString)
|
||||||
if err != nil {
|
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
|
// 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 {
|
for _, m := range msg {
|
||||||
printer.Printf("[upgrade/config] %s\n", m)
|
printer.Printf("[upgrade/config] %s\n", m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user told us to print this information out; do it!
|
// If the user told us to print this information out; do it!
|
||||||
if flags.printConfig {
|
printConfig, ok := cmdutil.ValueFromFlagsOrConfig(flagSet, options.PrintConfig, printConfigCfg, &flags.printConfig).(*bool)
|
||||||
printConfiguration(&cfg.ClusterConfiguration, os.Stdout, printer)
|
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
|
// 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
|
// printConfiguration prints the external version of the API to yaml
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
@@ -53,25 +54,18 @@ users:
|
|||||||
client-certificate-data:
|
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) {
|
func TestEnforceRequirements(t *testing.T) {
|
||||||
tmpDir := testutil.SetupTempDir(t)
|
tmpDir := testutil.SetupTempDir(t)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
fullPath := filepath.Join(tmpDir, "test-config-file")
|
fullPath := filepath.Join(tmpDir, "test-config-file")
|
||||||
f, err := os.Create(fullPath)
|
f, err := os.Create(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unable to create test file %q: %v", fullPath, err)
|
t.Errorf("Unable to create test file %q: %v", fullPath, err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
if _, err = f.WriteString(testConfigToken); err != nil {
|
if _, err = f.WriteString(testConfigToken); err != nil {
|
||||||
t.Errorf("Unable to write test file %q: %v", fullPath, err)
|
t.Errorf("Unable to write test file %q: %v", fullPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tcases := []struct {
|
tcases := []struct {
|
||||||
name string
|
name string
|
||||||
newK8sVersion string
|
newK8sVersion string
|
||||||
@@ -106,8 +100,7 @@ func TestEnforceRequirements(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tcases {
|
for _, tt := range tcases {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
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 {
|
if err == nil && len(tt.expectedErr) != 0 {
|
||||||
t.Error("Expected error, but got success")
|
t.Error("Expected error, but got success")
|
||||||
}
|
}
|
||||||
@@ -123,7 +116,6 @@ func TestEnforceRequirements(t *testing.T) {
|
|||||||
if err != nil && !strings.Contains(err.Error(), expErr) {
|
if err != nil && !strings.Contains(err.Error(), expErr) {
|
||||||
t.Fatalf("enforceRequirements returned unexpected error, expected: %s, got %v", expErr, err)
|
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/pkg/errors"
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
client "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
@@ -37,6 +39,7 @@ import (
|
|||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
type diffFlags struct {
|
type diffFlags struct {
|
||||||
@@ -74,7 +77,11 @@ func newCmdDiff(out io.Writer) *cobra.Command {
|
|||||||
flags.schedulerManifestPath); err != nil {
|
flags.schedulerManifestPath); err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDiff(flags *diffFlags, args []string) error {
|
// FetchInitConfigurationFunc defines the signature of the function which will fetch InitConfiguration from cluster.
|
||||||
var err error
|
type FetchInitConfigurationFunc func(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error)
|
||||||
var cfg *kubeadmapi.InitConfiguration
|
|
||||||
if flags.cfgPath != "" {
|
func runDiff(fs *pflag.FlagSet, flags *diffFlags, args []string, fetchInitConfigurationFromCluster FetchInitConfigurationFunc) error {
|
||||||
cfg, err = configutil.LoadInitConfigurationFromFile(flags.cfgPath, configutil.LoadOrDefaultConfigurationOptions{
|
upgradeCfg, err := configutil.LoadUpgradeConfig(flags.cfgPath)
|
||||||
SkipCRIDetect: true,
|
if err != nil {
|
||||||
})
|
return err
|
||||||
} 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)
|
|
||||||
}
|
}
|
||||||
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the version is specified in config file, pick up that value.
|
// Pick up the version from the ClusterConfiguration.
|
||||||
if cfg.KubernetesVersion != "" {
|
if initCfg.KubernetesVersion != "" {
|
||||||
flags.newK8sVersionStr = cfg.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 flags.newK8sVersionStr == "" {
|
||||||
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If option was specified in both args and config file, args will overwrite the config file.
|
// If option was specified in both args and config file, args will overwrite the config file.
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
flags.newK8sVersionStr = args[0]
|
flags.newK8sVersionStr = args[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = version.ParseSemantic(flags.newK8sVersionStr)
|
_, err = version.ParseSemantic(flags.newK8sVersionStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
for spec, pod := range specs {
|
||||||
var path string
|
var path string
|
||||||
switch spec {
|
switch spec {
|
||||||
@@ -164,7 +170,6 @@ func runDiff(flags *diffFlags, args []string) error {
|
|||||||
klog.Errorf("[diff] unknown spec %v", spec)
|
klog.Errorf("[diff] unknown spec %v", spec)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newManifest, err := kubeadmutil.MarshalToYaml(&pod, corev1.SchemeGroupVersion)
|
newManifest, err := kubeadmutil.MarshalToYaml(&pod, corev1.SchemeGroupVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -183,7 +188,7 @@ func runDiff(flags *diffFlags, args []string) error {
|
|||||||
B: difflib.SplitLines(string(newManifest)),
|
B: difflib.SplitLines(string(newManifest)),
|
||||||
FromFile: path,
|
FromFile: path,
|
||||||
ToFile: "new manifest",
|
ToFile: "new manifest",
|
||||||
Context: flags.contextLines,
|
Context: cmdutil.ValueFromFlagsOrConfig(fs, "context-lines", upgradeCfg.Diff.DiffContextLines, flags.contextLines).(int),
|
||||||
}
|
}
|
||||||
|
|
||||||
difflib.WriteUnifiedDiff(flags.out, diff)
|
difflib.WriteUnifiedDiff(flags.out, diff)
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
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) {
|
func createTestRunDiffFile(contents []byte) (string, error) {
|
||||||
@@ -42,23 +44,25 @@ func createTestRunDiffFile(contents []byte) (string, error) {
|
|||||||
return file.Name(), nil
|
return file.Name(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunDiff(t *testing.T) {
|
func fakeFetchInitConfig(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||||
currentVersion := "v" + constants.CurrentKubernetesVersion.String()
|
return &kubeadmapi.InitConfiguration{
|
||||||
|
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
|
||||||
|
KubernetesVersion: "v1.0.1",
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunDiff(t *testing.T) {
|
||||||
// create a temporary file with valid ClusterConfiguration
|
// create a temporary file with valid ClusterConfiguration
|
||||||
testUpgradeDiffConfigContents := []byte(fmt.Sprintf(`
|
testUpgradeDiffConfigContents := []byte(fmt.Sprintf(`
|
||||||
apiVersion: %s
|
apiVersion: %s
|
||||||
kind: InitConfiguration
|
kind: UpgradeConfiguration
|
||||||
---
|
contextLines: 4`, kubeadmapiv1.SchemeGroupVersion.String()))
|
||||||
apiVersion: %[1]s
|
|
||||||
kind: ClusterConfiguration
|
|
||||||
kubernetesVersion: %s`, kubeadmapiv1.SchemeGroupVersion.String(), currentVersion))
|
|
||||||
testUpgradeDiffConfig, err := createTestRunDiffFile(testUpgradeDiffConfigContents)
|
testUpgradeDiffConfig, err := createTestRunDiffFile(testUpgradeDiffConfigContents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.Remove(testUpgradeDiffConfig)
|
defer os.Remove(testUpgradeDiffConfig)
|
||||||
|
|
||||||
// create a temporary manifest file with dummy contents
|
// create a temporary manifest file with dummy contents
|
||||||
testUpgradeDiffManifestContents := []byte("some-contents")
|
testUpgradeDiffManifestContents := []byte("some-contents")
|
||||||
testUpgradeDiffManifest, err := createTestRunDiffFile(testUpgradeDiffManifestContents)
|
testUpgradeDiffManifest, err := createTestRunDiffFile(testUpgradeDiffManifestContents)
|
||||||
@@ -67,6 +71,13 @@ kubernetesVersion: %s`, kubeadmapiv1.SchemeGroupVersion.String(), currentVersion
|
|||||||
}
|
}
|
||||||
defer os.Remove(testUpgradeDiffManifest)
|
defer os.Remove(testUpgradeDiffManifest)
|
||||||
|
|
||||||
|
kubeConfigPath, err := createTestRunDiffFile([]byte(testConfigToken))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
//nolint:errcheck
|
||||||
|
defer os.Remove(kubeConfigPath)
|
||||||
|
|
||||||
flags := &diffFlags{
|
flags := &diffFlags{
|
||||||
cfgPath: "",
|
cfgPath: "",
|
||||||
out: io.Discard,
|
out: io.Discard,
|
||||||
@@ -118,12 +129,14 @@ kubernetesVersion: %s`, kubeadmapiv1.SchemeGroupVersion.String(), currentVersion
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
flags.cfgPath = tc.cfgPath
|
flags.cfgPath = tc.cfgPath
|
||||||
|
flags.kubeConfigPath = kubeConfigPath
|
||||||
|
cmd := newCmdDiff(os.Stdout)
|
||||||
if tc.setManifestPath {
|
if tc.setManifestPath {
|
||||||
flags.apiServerManifestPath = tc.manifestPath
|
flags.apiServerManifestPath = tc.manifestPath
|
||||||
flags.controllerManagerManifestPath = tc.manifestPath
|
flags.controllerManagerManifestPath = tc.manifestPath
|
||||||
flags.schedulerManifestPath = 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)
|
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"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node"
|
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/upgrade/node"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"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"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
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
|
// 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.
|
// supported by this api will be exposed as a flag.
|
||||||
type nodeOptions struct {
|
type nodeOptions struct {
|
||||||
|
cfgPath string
|
||||||
kubeConfigPath string
|
kubeConfigPath string
|
||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
@@ -57,7 +59,8 @@ type nodeData struct {
|
|||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
dryRun bool
|
dryRun bool
|
||||||
cfg *kubeadmapi.InitConfiguration
|
cfg *kubeadmapi.UpgradeConfiguration
|
||||||
|
initCfg *kubeadmapi.InitConfiguration
|
||||||
isControlPlaneNode bool
|
isControlPlaneNode bool
|
||||||
client clientset.Interface
|
client clientset.Interface
|
||||||
patchesDir string
|
patchesDir string
|
||||||
@@ -75,6 +78,10 @@ func newCmdNode(out io.Writer) *cobra.Command {
|
|||||||
Use: "node",
|
Use: "node",
|
||||||
Short: "Upgrade commands for a node in the cluster",
|
Short: "Upgrade commands for a node in the cluster",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nodeRunner.Run(args)
|
return nodeRunner.Run(args)
|
||||||
},
|
},
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -83,6 +90,7 @@ func newCmdNode(out io.Writer) *cobra.Command {
|
|||||||
// adds flags to the node command
|
// adds flags to the node command
|
||||||
// flags could be eventually inherited by the sub-commands automatically generated for phases
|
// flags could be eventually inherited by the sub-commands automatically generated for phases
|
||||||
addUpgradeNodeFlags(cmd.Flags(), nodeOptions)
|
addUpgradeNodeFlags(cmd.Flags(), nodeOptions)
|
||||||
|
options.AddConfigFlag(cmd.Flags(), &nodeOptions.cfgPath)
|
||||||
options.AddPatchesFlag(cmd.Flags(), &nodeOptions.patchesDir)
|
options.AddPatchesFlag(cmd.Flags(), &nodeOptions.patchesDir)
|
||||||
|
|
||||||
// initialize the workflow runner with the list of phases
|
// 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
|
// sets the data builder function, that will be used by the runner
|
||||||
// both when running the entire workflow or single phases
|
// both when running the entire workflow or single phases
|
||||||
nodeRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (workflow.RunData, error) {
|
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
|
// 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.
|
// 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
|
// 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
|
// 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
|
// Checks if a node is a control-plane node by looking up the kube-apiserver manifest file
|
||||||
isControlPlaneNode := true
|
isControlPlaneNode := true
|
||||||
filepath := constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory())
|
filepath := constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory())
|
||||||
if _, err := os.Stat(filepath); os.IsNotExist(err) {
|
if _, err := os.Stat(filepath); os.IsNotExist(err) {
|
||||||
isControlPlaneNode = false
|
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.
|
// 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 {
|
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 {
|
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
|
// 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
|
// 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
|
// (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 {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Also set the union of pre-flight errors to JoinConfiguration, to provide a consistent view of the runtime configuration:
|
// 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{
|
return &nodeData{
|
||||||
etcdUpgrade: options.etcdUpgrade,
|
cfg: upgradeCfg,
|
||||||
renewCerts: options.renewCerts,
|
dryRun: *dryRun,
|
||||||
dryRun: options.dryRun,
|
initCfg: initCfg,
|
||||||
cfg: cfg,
|
|
||||||
client: client,
|
client: client,
|
||||||
isControlPlaneNode: isControlPlaneNode,
|
isControlPlaneNode: isControlPlaneNode,
|
||||||
patchesDir: options.patchesDir,
|
|
||||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||||
kubeConfigPath: options.kubeConfigPath,
|
kubeConfigPath: nodeOptions.kubeConfigPath,
|
||||||
outputWriter: out,
|
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
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,11 +221,16 @@ func (d *nodeData) RenewCerts() bool {
|
|||||||
return d.renewCerts
|
return d.renewCerts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cfg returns initConfiguration.
|
// Cfg returns upgradeConfiguration.
|
||||||
func (d *nodeData) Cfg() *kubeadmapi.InitConfiguration {
|
func (d *nodeData) Cfg() *kubeadmapi.UpgradeConfiguration {
|
||||||
return d.cfg
|
return d.cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitCfg returns the InitConfiguration.
|
||||||
|
func (d *nodeData) InitCfg() *kubeadmapi.InitConfiguration {
|
||||||
|
return d.initCfg
|
||||||
|
}
|
||||||
|
|
||||||
// IsControlPlaneNode returns the isControlPlaneNode flag.
|
// IsControlPlaneNode returns the isControlPlaneNode flag.
|
||||||
func (d *nodeData) IsControlPlaneNode() bool {
|
func (d *nodeData) IsControlPlaneNode() bool {
|
||||||
return d.isControlPlaneNode
|
return d.isControlPlaneNode
|
||||||
|
|||||||
@@ -27,14 +27,17 @@ import (
|
|||||||
"github.com/lithammer/dedent"
|
"github.com/lithammer/dedent"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
|
outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
|
||||||
outputapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/v1alpha3"
|
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"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
@@ -64,13 +67,16 @@ func newCmdPlan(apf *applyPlanFlags) *cobra.Command {
|
|||||||
Use: "plan [version] [flags]",
|
Use: "plan [version] [flags]",
|
||||||
Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable.",
|
Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable.",
|
||||||
Long: upgradePlanLongDesc,
|
Long: upgradePlanLongDesc,
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
printer, err := outputFlags.ToPrinter()
|
printer, err := outputFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not construct output printer")
|
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
|
// 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.
|
// 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] verifying health of cluster")
|
||||||
klog.V(1).Infoln("[upgrade/plan] retrieving configuration from 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently this is the only method we have for distinguishing
|
// Currently this is the only method we have for distinguishing
|
||||||
// external etcd vs static pod etcd
|
// external etcd vs static pod etcd
|
||||||
isExternalEtcd := cfg.Etcd.External != nil
|
isExternalEtcd := initCfg.Etcd.External != nil
|
||||||
|
|
||||||
// Compute which upgrade possibilities there are
|
// Compute which upgrade possibilities there are
|
||||||
klog.V(1).Infoln("[upgrade/plan] computing upgrade possibilities")
|
klog.V(1).Infoln("[upgrade/plan] computing upgrade possibilities")
|
||||||
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "[upgrade/versions] FATAL")
|
return errors.Wrap(err, "[upgrade/versions] FATAL")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the current state of the component configs
|
// Fetch the current state of the component configs
|
||||||
klog.V(1).Infoln("[upgrade/plan] analysing component config version states")
|
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 {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "[upgrade/versions] FATAL")
|
return errors.WithMessage(err, "[upgrade/versions] FATAL")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
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) {
|
if flagSet.Changed(name) {
|
||||||
return flagValue
|
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.
|
// assume config has all the defaults set correctly.
|
||||||
return cfgValue
|
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,
|
flagValue: false,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "nil bool is converted to false",
|
||||||
|
cfg: (*bool)(nil),
|
||||||
|
flagValue: false,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
type options struct {
|
type options struct {
|
||||||
@@ -140,11 +146,15 @@ func TestValueFromFlagsOrConfig(t *testing.T) {
|
|||||||
fs.BoolVar(&fakeOptions.bar, "bar", false, "")
|
fs.BoolVar(&fakeOptions.bar, "bar", false, "")
|
||||||
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
err := fs.Set(tt.flag, fmt.Sprintf("%v", tt.flagValue))
|
if tt.flag != "" {
|
||||||
if err != nil {
|
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)
|
t.Fatalf("failed to set the value of the flag %v", tt.flagValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
actualResult := ValueFromFlagsOrConfig(&fs, tt.flag, tt.cfg, tt.flagValue)
|
actualResult := ValueFromFlagsOrConfig(&fs, tt.flag, tt.cfg, tt.flagValue)
|
||||||
|
if result, ok := actualResult.(*bool); ok {
|
||||||
|
actualResult = *result
|
||||||
|
}
|
||||||
if actualResult != tt.expected {
|
if actualResult != tt.expected {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed ValueFromFlagsOrConfig:\n\texpected: %s\n\t actual: %s",
|
"failed ValueFromFlagsOrConfig:\n\texpected: %s\n\t actual: %s",
|
||||||
|
|||||||
@@ -452,6 +452,8 @@ const (
|
|||||||
EtcdUserName string = "kubeadm-etcd"
|
EtcdUserName string = "kubeadm-etcd"
|
||||||
// ServiceAccountKeyReadersGroupName is the group of users that are allowed to read the service account private key.
|
// ServiceAccountKeyReadersGroupName is the group of users that are allowed to read the service account private key.
|
||||||
ServiceAccountKeyReadersGroupName string = "kubeadm-sa-key-readers"
|
ServiceAccountKeyReadersGroupName string = "kubeadm-sa-key-readers"
|
||||||
|
// UpgradeConfigurationKind is the string kind value for the UpgradeConfiguration struct
|
||||||
|
UpgradeConfigurationKind = "UpgradeConfiguration"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Package config contains utilities for managing the kubeadm configuration API.
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -490,3 +491,13 @@ func defaultEmptyMigrateMutators() migrateMutators {
|
|||||||
|
|
||||||
return *mutators
|
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 {
|
func GroupVersionKindsHasResetConfiguration(gvks ...schema.GroupVersionKind) bool {
|
||||||
return GroupVersionKindsHasKind(gvks, constants.ResetConfigurationKind)
|
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