mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 05:46:16 +00:00
kubeadm: improve some grammar issues and add some unit test cases
This commit is contained in:
parent
595482d264
commit
a2f8d31c65
@ -18,32 +18,27 @@ limitations under the License.
|
|||||||
package apply
|
package apply
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"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/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
"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"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
|
||||||
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||||
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAddonPhase returns the addon Cobra command
|
// NewAddonPhase returns a new addon phase.
|
||||||
func NewAddonPhase() workflow.Phase {
|
func NewAddonPhase() workflow.Phase {
|
||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "addon",
|
Name: "addon",
|
||||||
Short: "Install required addons for passing conformance tests",
|
Short: "Install the default kubeadm addons",
|
||||||
Long: cmdutil.MacroCommandLongDescription,
|
Long: cmdutil.MacroCommandLongDescription,
|
||||||
Phases: []workflow.Phase{
|
Phases: []workflow.Phase{
|
||||||
{
|
{
|
||||||
@ -54,13 +49,13 @@ func NewAddonPhase() workflow.Phase {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "coredns",
|
Name: "coredns",
|
||||||
Short: "Install the CoreDNS addon to a Kubernetes cluster",
|
Short: "Install the CoreDNS addon",
|
||||||
InheritFlags: getAddonPhaseFlags("coredns"),
|
InheritFlags: getAddonPhaseFlags("coredns"),
|
||||||
Run: runCoreDNSAddon,
|
Run: runCoreDNSAddon,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "kube-proxy",
|
Name: "kube-proxy",
|
||||||
Short: "Install the kube-proxy addon to a Kubernetes cluster",
|
Short: "Install the kube-proxy addon",
|
||||||
InheritFlags: getAddonPhaseFlags("kube-proxy"),
|
InheritFlags: getAddonPhaseFlags("kube-proxy"),
|
||||||
Run: runKubeProxyAddon,
|
Run: runKubeProxyAddon,
|
||||||
},
|
},
|
||||||
@ -74,10 +69,9 @@ func shouldUpgradeAddons(client clientset.Interface, cfg *kubeadmapi.InitConfigu
|
|||||||
return false, errors.Wrapf(err, "failed to determine whether all the control plane instances have been upgraded")
|
return false, errors.Wrapf(err, "failed to determine whether all the control plane instances have been upgraded")
|
||||||
}
|
}
|
||||||
if len(unupgradedControlPlanes) > 0 {
|
if len(unupgradedControlPlanes) > 0 {
|
||||||
fmt.Fprintf(out, "[upgrade/addons] skip upgrade addons because control plane instances %v have not been upgraded\n", unupgradedControlPlanes)
|
fmt.Fprintf(out, "[upgrade/addons] Skipping upgrade of addons because control plane instances %v have not been upgraded\n", unupgradedControlPlanes)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +83,7 @@ func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.I
|
|||||||
return data.InitCfg(), data.Client(), data.PatchesDir(), data.OutputWriter(), data.DryRun(), nil
|
return data.InitCfg(), data.Client(), data.PatchesDir(), data.OutputWriter(), data.DryRun(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runCoreDNSAddon installs CoreDNS addon to a Kubernetes cluster
|
// runCoreDNSAddon installs the CoreDNS addon.
|
||||||
func runCoreDNSAddon(c workflow.RunData) error {
|
func runCoreDNSAddon(c workflow.RunData) error {
|
||||||
cfg, client, patchesDir, out, dryRun, err := getInitData(c)
|
cfg, client, patchesDir, out, dryRun, err := getInitData(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -104,25 +98,6 @@ func runCoreDNSAddon(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the coredns ConfigMap is missing, show a warning and assume that the
|
|
||||||
// DNS addon was skipped during "kubeadm init", and that its redeployment on upgrade is not desired.
|
|
||||||
//
|
|
||||||
// TODO: remove this once "kubeadm upgrade apply" phases are supported:
|
|
||||||
// https://github.com/kubernetes/kubeadm/issues/1318
|
|
||||||
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(
|
|
||||||
context.TODO(),
|
|
||||||
kubeadmconstants.CoreDNSConfigMap,
|
|
||||||
metav1.GetOptions{},
|
|
||||||
); err != nil && apierrors.IsNotFound(err) {
|
|
||||||
klog.Warningf("the ConfigMaps %q in the namespace %q were not found. "+
|
|
||||||
"Assuming that a DNS server was not deployed for this cluster. "+
|
|
||||||
"Note that once 'kubeadm upgrade apply' supports phases you "+
|
|
||||||
"will have to skip the DNS upgrade manually",
|
|
||||||
kubeadmconstants.CoreDNSConfigMap,
|
|
||||||
metav1.NamespaceSystem)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upgrade CoreDNS
|
// Upgrade CoreDNS
|
||||||
if err := dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, dryRun); err != nil {
|
if err := dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, dryRun); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -131,7 +106,7 @@ func runCoreDNSAddon(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster
|
// runKubeProxyAddon installs the KubeProxy addon.
|
||||||
func runKubeProxyAddon(c workflow.RunData) error {
|
func runKubeProxyAddon(c workflow.RunData) error {
|
||||||
cfg, client, _, out, dryRun, err := getInitData(c)
|
cfg, client, _, out, dryRun, err := getInitData(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -146,25 +121,6 @@ func runKubeProxyAddon(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the kube-proxy ConfigMap is missing, show a warning and assume that kube-proxy
|
|
||||||
// was skipped during "kubeadm init", and that its redeployment on upgrade is not desired.
|
|
||||||
//
|
|
||||||
// TODO: remove this once "kubeadm upgrade apply" phases are supported:
|
|
||||||
// https://github.com/kubernetes/kubeadm/issues/1318
|
|
||||||
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(
|
|
||||||
context.TODO(),
|
|
||||||
kubeadmconstants.KubeProxyConfigMap,
|
|
||||||
metav1.GetOptions{},
|
|
||||||
); err != nil && apierrors.IsNotFound(err) {
|
|
||||||
klog.Warningf("the ConfigMap %q in the namespace %q was not found. "+
|
|
||||||
"Assuming that kube-proxy was not deployed for this cluster. "+
|
|
||||||
"Note that once 'kubeadm upgrade apply' supports phases you "+
|
|
||||||
"will have to skip the kube-proxy upgrade manually",
|
|
||||||
kubeadmconstants.KubeProxyConfigMap,
|
|
||||||
metav1.NamespaceSystem)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upgrade kube-proxy
|
// Upgrade kube-proxy
|
||||||
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, dryRun); err != nil {
|
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, dryRun); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,12 +30,11 @@ import (
|
|||||||
nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBootstrapTokenPhase returns the phase to bootstrapToken
|
// NewBootstrapTokenPhase returns a new bootstrap-token phase.
|
||||||
func NewBootstrapTokenPhase() workflow.Phase {
|
func NewBootstrapTokenPhase() workflow.Phase {
|
||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "bootstrap-token",
|
Name: "bootstrap-token",
|
||||||
Aliases: []string{"bootstraptoken"},
|
Short: "Configures bootstrap token and cluster-info RBAC rules",
|
||||||
Short: "Generates bootstrap tokens used to join a node to a cluster",
|
|
||||||
InheritFlags: []string{
|
InheritFlags: []string{
|
||||||
options.CfgPath,
|
options.CfgPath,
|
||||||
options.KubeconfigPath,
|
options.KubeconfigPath,
|
||||||
@ -56,7 +55,7 @@ func runBootstrapToken(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[bootstrap-token] Configuring cluster-info ConfigMap, RBAC Roles")
|
fmt.Println("[bootstrap-token] Configuring the cluster-info ConfigMap and RBAC roles")
|
||||||
|
|
||||||
client := data.Client()
|
client := data.Client()
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewControlPlanePhase creates a kubeadm workflow phase that implements handling of control-plane upgrade.
|
// NewControlPlanePhase returns a new control-plane phase.
|
||||||
func NewControlPlanePhase() workflow.Phase {
|
func NewControlPlanePhase() workflow.Phase {
|
||||||
phase := workflow.Phase{
|
phase := workflow.Phase{
|
||||||
Name: "control-plane",
|
Name: "control-plane",
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewKubeconfigPhase creates a kubeadm workflow phase that implements handling of kubeconfig upgrade.
|
// NewKubeconfigPhase returns a new kubeconfig phase.
|
||||||
func NewKubeconfigPhase() workflow.Phase {
|
func NewKubeconfigPhase() workflow.Phase {
|
||||||
phase := workflow.Phase{
|
phase := workflow.Phase{
|
||||||
Name: "kubeconfig",
|
Name: "kubeconfig",
|
||||||
@ -59,7 +59,7 @@ func runKubeconfig() func(c workflow.RunData) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[upgrade] The kubeconfig for this node was successfully updated!")
|
fmt.Println("[upgrade] The kubeconfig files for this node were successfully updated!")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ var (
|
|||||||
`)
|
`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewKubeletConfigPhase creates a kubeadm workflow phase that implements handling of kubelet-config upgrade.
|
// NewKubeletConfigPhase returns a new kubelet-config phase.
|
||||||
func NewKubeletConfigPhase() workflow.Phase {
|
func NewKubeletConfigPhase() workflow.Phase {
|
||||||
phase := workflow.Phase{
|
phase := workflow.Phase{
|
||||||
Name: "kubelet-config",
|
Name: "kubelet-config",
|
||||||
@ -59,15 +59,14 @@ func runKubeletConfigPhase(c workflow.RunData) error {
|
|||||||
|
|
||||||
initCfg, dryRun := data.InitCfg(), data.DryRun()
|
initCfg, dryRun := data.InitCfg(), 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 of dry-running.
|
||||||
// If not dry-running, the kubelet config file will be backed up to /etc/kubernetes/tmp/ dir, so that it could be
|
// If not dry-running, the kubelet config file will be backed up to /etc/kubernetes/tmp/ dir, so that it could be
|
||||||
// recovered if there is anything goes wrong.
|
// recovered if anything goes wrong.
|
||||||
err := upgrade.WriteKubeletConfigFiles(initCfg, data.PatchesDir(), dryRun, data.OutputWriter())
|
err := upgrade.WriteKubeletConfigFiles(initCfg, data.PatchesDir(), dryRun, data.OutputWriter())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[upgrade] The configuration for this node was successfully updated!")
|
fmt.Println("[upgrade] The kubelet configuration for this node was successfully updated!")
|
||||||
fmt.Println("[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,12 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPreflightPhase creates a kubeadm workflow phase that implements preflight checks for kubeadm upgrade apply.
|
// NewPreflightPhase returns a new prefight phase.
|
||||||
func NewPreflightPhase() workflow.Phase {
|
func NewPreflightPhase() workflow.Phase {
|
||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "preflight",
|
Name: "preflight",
|
||||||
Short: "Run upgrade apply pre-flight checks",
|
Short: "Run upgrade apply preflight checks",
|
||||||
Long: "Run pre-flight checks for kubeadm upgrade apply.",
|
Long: "Run preflight checks for kubeadm upgrade apply.",
|
||||||
Run: runPreflight,
|
Run: runPreflight,
|
||||||
InheritFlags: []string{
|
InheritFlags: []string{
|
||||||
options.CfgPath,
|
options.CfgPath,
|
||||||
@ -58,13 +58,12 @@ func NewPreflightPhase() workflow.Phase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// runPreflight executes preflight checks logic.
|
|
||||||
func runPreflight(c workflow.RunData) error {
|
func runPreflight(c workflow.RunData) error {
|
||||||
data, ok := c.(Data)
|
data, ok := c.(Data)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("preflight phase invoked with an invalid data struct")
|
return errors.New("preflight phase invoked with an invalid data struct")
|
||||||
}
|
}
|
||||||
fmt.Println("[preflight] Running pre-flight checks")
|
fmt.Println("[preflight] Running preflight checks")
|
||||||
|
|
||||||
printer := &output.TextPrinter{}
|
printer := &output.TextPrinter{}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ func runPreflight(c workflow.RunData) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run healthchecks against the cluster
|
// Run healthchecks against the cluster
|
||||||
klog.V(1).Infoln("[upgrade/apply] verifying health of cluster")
|
klog.V(1).Infoln("[upgrade/apply] Verifying the cluster health")
|
||||||
if err := upgrade.CheckClusterHealth(client, &initCfg.ClusterConfiguration, ignorePreflightErrors, printer); err != nil {
|
if err := upgrade.CheckClusterHealth(client, &initCfg.ClusterConfiguration, ignorePreflightErrors, printer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -94,7 +93,7 @@ func runPreflight(c workflow.RunData) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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(&initCfg.ClusterConfiguration); err != nil {
|
if err := configutil.NormalizeKubernetesVersion(&initCfg.ClusterConfiguration); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -110,7 +109,7 @@ func runPreflight(c workflow.RunData) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
versionGetter := upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(client), initCfg.KubernetesVersion)
|
versionGetter := upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(client), initCfg.KubernetesVersion)
|
||||||
if err := EnforceVersionPolicies(initCfg.KubernetesVersion, upgradeVersion, data.AllowExperimentalUpgrades(), data.AllowRCUpgrades(), data.ForceUpgrade(), versionGetter); err != nil {
|
if err := enforceVersionPolicies(initCfg.KubernetesVersion, upgradeVersion, data.AllowExperimentalUpgrades(), data.AllowRCUpgrades(), data.ForceUpgrade(), versionGetter); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,23 +133,23 @@ func runPreflight(c workflow.RunData) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnforceVersionPolicies makes sure that the version the user specified is valid to upgrade to
|
// enforceVersionPolicies makes sure that the version the user specified is valid to upgrade to
|
||||||
// There are both fatal and skippable (with --force) errors
|
// There are both fatal and skippable (with --force) errors
|
||||||
func EnforceVersionPolicies(newK8sVersionStr string, newK8sVersion *version.Version, allowExperimentalUpgrades, allowRCUpgrades, force bool, versionGetter upgrade.VersionGetter) error {
|
func enforceVersionPolicies(newK8sVersionStr string, newK8sVersion *version.Version, allowExperimentalUpgrades, allowRCUpgrades, force bool, versionGetter upgrade.VersionGetter) error {
|
||||||
fmt.Printf("[upgrade/version] You have chosen to change the cluster version to %q\n", newK8sVersionStr)
|
fmt.Printf("[upgrade/version] You have chosen to upgrade the cluster version to %q\n", newK8sVersionStr)
|
||||||
|
|
||||||
versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, newK8sVersionStr, newK8sVersion, allowExperimentalUpgrades, allowRCUpgrades)
|
versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, newK8sVersionStr, newK8sVersion, allowExperimentalUpgrades, allowRCUpgrades)
|
||||||
if versionSkewErrs != nil {
|
if versionSkewErrs != nil {
|
||||||
|
|
||||||
if len(versionSkewErrs.Mandatory) > 0 {
|
if len(versionSkewErrs.Mandatory) > 0 {
|
||||||
return errors.Errorf("the --version argument is invalid due to these fatal errors:\n\n%v\nPlease fix the misalignments highlighted above and try upgrading again",
|
return errors.Errorf("the version argument is invalid due to these fatal errors:\n\n%v\nPlease fix the misalignments highlighted above and try upgrading again",
|
||||||
kubeadmutil.FormatErrMsg(versionSkewErrs.Mandatory))
|
kubeadmutil.FormatErrMsg(versionSkewErrs.Mandatory))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(versionSkewErrs.Skippable) > 0 {
|
if len(versionSkewErrs.Skippable) > 0 {
|
||||||
// Return the error if the user hasn't specified the --force flag
|
// Return the error if the user hasn't specified the --force flag
|
||||||
if !force {
|
if !force {
|
||||||
return errors.Errorf("the --version argument is invalid due to these errors:\n\n%v\nCan be bypassed if you pass the --force flag",
|
return errors.Errorf("the version argument is invalid due to these errors:\n\n%v\nCan be bypassed if you pass the --force flag",
|
||||||
kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable))
|
kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable))
|
||||||
}
|
}
|
||||||
// Soft errors found, but --force was specified
|
// Soft errors found, but --force was specified
|
||||||
|
@ -39,12 +39,12 @@ func NewUploadConfigPhase() workflow.Phase {
|
|||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "upload-config",
|
Name: "upload-config",
|
||||||
Aliases: []string{"uploadconfig"},
|
Aliases: []string{"uploadconfig"},
|
||||||
Short: "Upload the kubeadm and kubelet configuration to a ConfigMap",
|
Short: "Upload the kubeadm and kubelet configurations to a ConfigMaps",
|
||||||
Long: cmdutil.MacroCommandLongDescription,
|
Long: cmdutil.MacroCommandLongDescription,
|
||||||
Phases: []workflow.Phase{
|
Phases: []workflow.Phase{
|
||||||
{
|
{
|
||||||
Name: "all",
|
Name: "all",
|
||||||
Short: "Upload all configuration to a config map",
|
Short: "Upload all the configurations to ConfigMaps",
|
||||||
RunAllSiblings: true,
|
RunAllSiblings: true,
|
||||||
InheritFlags: getUploadConfigPhaseFlags(),
|
InheritFlags: getUploadConfigPhaseFlags(),
|
||||||
},
|
},
|
||||||
@ -56,7 +56,7 @@ func NewUploadConfigPhase() workflow.Phase {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "kubelet",
|
Name: "kubelet",
|
||||||
Short: "Upload the kubelet component config to a ConfigMap",
|
Short: "Upload the kubelet configuration config to a ConfigMap",
|
||||||
Run: runUploadKubeletConfig,
|
Run: runUploadKubeletConfig,
|
||||||
InheritFlags: getUploadConfigPhaseFlags(),
|
InheritFlags: getUploadConfigPhaseFlags(),
|
||||||
},
|
},
|
||||||
@ -99,19 +99,19 @@ func runUploadKubeletConfig(c workflow.RunData) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dryRun {
|
if dryRun {
|
||||||
fmt.Println("[dryrun] Would upload the kubelet component config to a ConfigMap")
|
fmt.Println("[dryrun] Would upload the kubelet configuration to a ConfigMap")
|
||||||
fmt.Println("[dryrun] Would write the CRISocket annotation for the control-plane node")
|
fmt.Println("[dryrun] Would write the CRISocket annotation for the control-plane node")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(1).Infoln("[upload-config] Uploading the kubelet component config to a ConfigMap")
|
klog.V(1).Infoln("[upload-config] Uploading the kubelet configuration to a ConfigMap")
|
||||||
if err = kubeletphase.CreateConfigMap(&cfg.ClusterConfiguration, client); err != nil {
|
if err = kubeletphase.CreateConfigMap(&cfg.ClusterConfiguration, client); err != nil {
|
||||||
return errors.Wrap(err, "error creating kubelet configuration ConfigMap")
|
return errors.Wrap(err, "error creating kubelet configuration ConfigMap")
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(1).Infoln("[upload-config] Preserving the CRISocket information for the control-plane node")
|
klog.V(1).Infoln("[upload-config] Preserving the CRISocket information for the control-plane node")
|
||||||
if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil {
|
if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil {
|
||||||
return errors.Wrap(err, "Error writing Crisocket information for the control-plane node")
|
return errors.Wrap(err, "error writing Crisocket information for the control-plane node")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -99,25 +99,21 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
applyData, ok := data.(*applyData)
|
applyData, ok := data.(*applyData)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("invalid data struct")
|
return errors.New("invalid data struct")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := applyRunner.Run(args); err != nil {
|
if err := applyRunner.Run(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.dryRun {
|
if flags.dryRun {
|
||||||
fmt.Println("[upgrade/successful] Finished dryrunning successfully!")
|
fmt.Println("[upgrade/successful] Finished dryrunning successfully!")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Printf("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", applyData.InitCfg().KubernetesVersion)
|
fmt.Printf("[upgrade/successful] SUCCESS! A control plane node of your cluster was upgraded to %q.\n\n", applyData.InitCfg().KubernetesVersion)
|
||||||
fmt.Println("")
|
fmt.Println("[upgrade/kubelet] Now please proceed with upgrading the rest of the nodes by following the right order.")
|
||||||
fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -133,7 +129,7 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||||||
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)
|
||||||
|
|
||||||
// initialize the workflow runner with the list of phases
|
// Initialize the workflow runner with the list of phases
|
||||||
applyRunner.AppendPhase(phases.NewPreflightPhase())
|
applyRunner.AppendPhase(phases.NewPreflightPhase())
|
||||||
applyRunner.AppendPhase(phases.NewControlPlanePhase())
|
applyRunner.AppendPhase(phases.NewControlPlanePhase())
|
||||||
applyRunner.AppendPhase(phases.NewUploadConfigPhase())
|
applyRunner.AppendPhase(phases.NewUploadConfigPhase())
|
||||||
@ -142,7 +138,7 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||||||
applyRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
applyRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
||||||
applyRunner.AppendPhase(phases.NewAddonPhase())
|
applyRunner.AppendPhase(phases.NewAddonPhase())
|
||||||
|
|
||||||
// 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
|
||||||
applyRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (workflow.RunData, error) {
|
applyRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (workflow.RunData, error) {
|
||||||
data, err := newApplyData(cmd, args, flags)
|
data, err := newApplyData(cmd, args, flags)
|
||||||
@ -156,7 +152,7 @@ func newCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||||||
return data, nil
|
return data, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
// binds the Runner to kubeadm upgrade apply command by altering
|
// Binds the Runner to kubeadm upgrade apply command by altering
|
||||||
// command help, adding --skip-phases flag and by adding phases subcommands
|
// command help, adding --skip-phases flag and by adding phases subcommands
|
||||||
applyRunner.BindToCommand(cmd)
|
applyRunner.BindToCommand(cmd)
|
||||||
|
|
||||||
@ -173,18 +169,23 @@ func newApplyData(cmd *cobra.Command, args []string, applyFlags *applyFlags) (*a
|
|||||||
}
|
}
|
||||||
|
|
||||||
upgradeVersion := upgradeCfg.Apply.KubernetesVersion
|
upgradeVersion := upgradeCfg.Apply.KubernetesVersion
|
||||||
// The version arg is mandatory, during upgrade apply, unless it's specified in the config file
|
// The version arg is mandatory, unless it's specified in the config file
|
||||||
if upgradeVersion == "" {
|
if upgradeVersion == "" {
|
||||||
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If option was specified in both args and config file, args will overwrite the config file.
|
// If the version was specified in both the arg and config file, the arg will overwrite the config file.
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
upgradeVersion = args[0]
|
upgradeVersion = args[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(applyFlags.ignorePreflightErrors, upgradeCfg.Apply.IgnorePreflightErrors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
force, ok := cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), "force", upgradeCfg.Apply.ForceUpgrade, &applyFlags.force).(*bool)
|
force, ok := cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), "force", upgradeCfg.Apply.ForceUpgrade, &applyFlags.force).(*bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, cmdutil.TypeMismatchErr("forceUpgrade", "bool")
|
return nil, cmdutil.TypeMismatchErr("forceUpgrade", "bool")
|
||||||
@ -239,10 +240,6 @@ func newApplyData(cmd *cobra.Command, args []string, applyFlags *applyFlags) (*a
|
|||||||
return nil, errors.Wrap(err, "[upgrade/init config] FATAL")
|
return nil, errors.Wrap(err, "[upgrade/init config] FATAL")
|
||||||
}
|
}
|
||||||
|
|
||||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(applyFlags.ignorePreflightErrors, upgradeCfg.Apply.IgnorePreflightErrors)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Also set the union of pre-flight errors to InitConfiguration, to provide a consistent view of the runtime configuration:
|
// Also set the union of pre-flight errors to InitConfiguration, to provide a consistent view of the runtime configuration:
|
||||||
initCfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
initCfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet)
|
||||||
|
|
||||||
@ -303,7 +300,7 @@ func (d *applyData) RenewCerts() bool {
|
|||||||
return d.renewCerts
|
return d.renewCerts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cfg returns upgradeConfiguration.
|
// Cfg returns the UpgradeConfiguration.
|
||||||
func (d *applyData) Cfg() *kubeadmapi.UpgradeConfiguration {
|
func (d *applyData) Cfg() *kubeadmapi.UpgradeConfiguration {
|
||||||
return d.cfg
|
return d.cfg
|
||||||
}
|
}
|
||||||
@ -338,17 +335,17 @@ func (d *applyData) SessionIsInteractive() bool {
|
|||||||
return !(d.nonInteractiveMode || d.dryRun || d.force)
|
return !(d.nonInteractiveMode || d.dryRun || d.force)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllowExperimentalUpgrades returns true if allow upgrading to an alpha/beta/release candidate version of Kubernetes.
|
// AllowExperimentalUpgrades returns true if upgrading to an alpha/beta/release candidate version of Kubernetes is allowed.
|
||||||
func (d *applyData) AllowExperimentalUpgrades() bool {
|
func (d *applyData) AllowExperimentalUpgrades() bool {
|
||||||
return d.allowExperimentalUpgrades
|
return d.allowExperimentalUpgrades
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllowRCUpgrades returns true if allow upgrading to a release candidate version of Kubernetes.
|
// AllowRCUpgrades returns true if upgrading to a release candidate version of Kubernetes is allowed.
|
||||||
func (d *applyData) AllowRCUpgrades() bool {
|
func (d *applyData) AllowRCUpgrades() bool {
|
||||||
return d.allowRCUpgrades
|
return d.allowRCUpgrades
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForceUpgrade returns true if force upgrading although some requirements might not be met.
|
// ForceUpgrade returns true if force-upgrading is enabled.
|
||||||
func (d *applyData) ForceUpgrade() bool {
|
func (d *applyData) ForceUpgrade() bool {
|
||||||
return d.force
|
return d.force
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,15 @@ limitations under the License.
|
|||||||
package upgrade
|
package upgrade
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSessionIsInteractive(t *testing.T) {
|
func TestSessionIsInteractive(t *testing.T) {
|
||||||
@ -61,3 +69,128 @@ func TestSessionIsInteractive(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var testApplyConfig = fmt.Sprintf(`---
|
||||||
|
apiVersion: %s
|
||||||
|
apply:
|
||||||
|
certificateRenewal: true
|
||||||
|
etcdUpgrade: true
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
imagePullSerial: true
|
||||||
|
diff: {}
|
||||||
|
kind: UpgradeConfiguration
|
||||||
|
node:
|
||||||
|
certificateRenewal: true
|
||||||
|
etcdUpgrade: true
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
imagePullSerial: true
|
||||||
|
plan: {}
|
||||||
|
timeouts:
|
||||||
|
controlPlaneComponentHealthCheck: 4m0s
|
||||||
|
discovery: 5m0s
|
||||||
|
etcdAPICall: 2m0s
|
||||||
|
kubeletHealthCheck: 4m0s
|
||||||
|
kubernetesAPICall: 1m0s
|
||||||
|
tlsBootstrap: 5m0s
|
||||||
|
upgradeManifests: 5m0s
|
||||||
|
`, kubeadmapiv1.SchemeGroupVersion.String())
|
||||||
|
|
||||||
|
func TestNewApplyData(t *testing.T) {
|
||||||
|
// create temp directory
|
||||||
|
tmpDir, err := os.MkdirTemp("", "kubeadm-upgrade-apply-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unable to create temporary directory: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = os.RemoveAll(tmpDir)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// create config file
|
||||||
|
configFilePath := filepath.Join(tmpDir, "test-config-file")
|
||||||
|
cfgFile, err := os.Create(configFilePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unable to create file %q: %v", configFilePath, err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = cfgFile.Close()
|
||||||
|
}()
|
||||||
|
if _, err = cfgFile.WriteString(testApplyConfig); err != nil {
|
||||||
|
t.Fatalf("Unable to write file %q: %v", configFilePath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
flags map[string]string
|
||||||
|
validate func(*testing.T, *applyData)
|
||||||
|
expectedError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fails if no upgrade version set",
|
||||||
|
flags: map[string]string{
|
||||||
|
options.CfgPath: configFilePath,
|
||||||
|
},
|
||||||
|
expectedError: "missing one or more required arguments. Required arguments: [version]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fails if invalid preflight checks are provided",
|
||||||
|
args: []string{"v1.1.0"},
|
||||||
|
flags: map[string]string{
|
||||||
|
options.IgnorePreflightErrors: "all,something-else",
|
||||||
|
},
|
||||||
|
expectedError: "ignore-preflight-errors: Invalid value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fails if kubeconfig file doesn't exists",
|
||||||
|
args: []string{"v1.1.0"},
|
||||||
|
flags: map[string]string{
|
||||||
|
options.CfgPath: configFilePath,
|
||||||
|
options.KubeconfigPath: "invalid-kubeconfig-path",
|
||||||
|
},
|
||||||
|
expectedError: "couldn't create a Kubernetes client from file",
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: add more test cases here when the fake client for `kubeadm upgrade apply` can be injected
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
// initialize an external apply flags and inject it to the apply cmd
|
||||||
|
apf := &applyPlanFlags{
|
||||||
|
kubeConfigPath: kubeadmconstants.GetAdminKubeConfigPath(),
|
||||||
|
cfgPath: "",
|
||||||
|
featureGatesString: "",
|
||||||
|
allowExperimentalUpgrades: false,
|
||||||
|
allowRCUpgrades: false,
|
||||||
|
printConfig: false,
|
||||||
|
out: os.Stdout,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := newCmdApply(apf)
|
||||||
|
|
||||||
|
// sets cmd flags (that will be reflected on the init options)
|
||||||
|
for f, v := range tc.flags {
|
||||||
|
_ = cmd.Flags().Set(f, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := &applyFlags{
|
||||||
|
applyPlanFlags: apf,
|
||||||
|
etcdUpgrade: true,
|
||||||
|
renewCerts: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// test newApplyData method
|
||||||
|
data, err := newApplyData(cmd, tc.args, flags)
|
||||||
|
if err == nil && len(tc.expectedError) != 0 {
|
||||||
|
t.Error("Expected error, but got success")
|
||||||
|
}
|
||||||
|
if err != nil && (len(tc.expectedError) == 0 || !strings.Contains(err.Error(), tc.expectedError)) {
|
||||||
|
t.Fatalf("newApplyData returned unexpected error, expected: %s, got %v", tc.expectedError, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// exec additional validation on the returned value
|
||||||
|
if tc.validate != nil {
|
||||||
|
tc.validate(t, data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user