mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-08-03 20:44:14 -04:00
cli: skip k8s upgrade in case of outdated version (#1864)
If an unsupported, outdated k8s patch version is used, the user should still be able to run upgrade apply.
This commit is contained in:
parent
eb9bea1cff
commit
6bda62d397
9 changed files with 107 additions and 16 deletions
|
@ -127,9 +127,11 @@ func (i *initCmd) initialize(cmd *cobra.Command, newDialer func(validator atls.V
|
|||
return fmt.Errorf("reading cluster ID file: %w", err)
|
||||
}
|
||||
|
||||
k8sVersion, err := versions.NewValidK8sVersion(compatibility.EnsurePrefixV(conf.KubernetesVersion))
|
||||
// config validation does not check k8s patch version since upgrade may accept an outdated patch version.
|
||||
// init only supported up-to-date versions.
|
||||
k8sVersion, err := versions.NewValidK8sVersion(compatibility.EnsurePrefixV(conf.KubernetesVersion), true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("validating kubernetes version: %w", err)
|
||||
return fmt.Errorf("invalid Kubernetes version: %s", conf.KubernetesVersion)
|
||||
}
|
||||
i.log.Debugf("Validated k8s version as %s", k8sVersion)
|
||||
if versions.IsPreviewK8sVersion(k8sVersion) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/imagefetcher"
|
||||
"github.com/edgelesssys/constellation/v2/internal/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -94,6 +95,10 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Hand
|
|||
return err
|
||||
}
|
||||
|
||||
if err := handleInvalidK8sPatchVersion(cmd, conf.KubernetesVersion, flags.yes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var idFile clusterid.File
|
||||
if err := fileHandler.ReadJSON(constants.ClusterIDsFileName, &idFile); err != nil {
|
||||
return fmt.Errorf("reading cluster ID file: %w", err)
|
||||
|
@ -269,6 +274,24 @@ func (u *upgradeApplyCmd) parseUpgradeVars(cmd *cobra.Command, conf *config.Conf
|
|||
}
|
||||
}
|
||||
|
||||
// handleInvalidK8sPatchVersion checks if the Kubernetes patch version is supported and asks for confirmation if not.
|
||||
func handleInvalidK8sPatchVersion(cmd *cobra.Command, version string, yes bool) error {
|
||||
_, err := versions.NewValidK8sVersion(version, true)
|
||||
valid := err == nil
|
||||
|
||||
if !valid && !yes {
|
||||
confirmed, err := askToConfirm(cmd, fmt.Sprintf("WARNING: The Kubernetes patch version %s is not supported. If you continue, Kubernetes upgrades will be skipped. Do you want to continue anyway?", version))
|
||||
if err != nil {
|
||||
return fmt.Errorf("asking for confirmation: %w", err)
|
||||
}
|
||||
if !confirmed {
|
||||
return fmt.Errorf("aborted by user")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type imageFetcher interface {
|
||||
FetchReference(ctx context.Context,
|
||||
provider cloudprovider.Provider, attestationVariant variant.Variant,
|
||||
|
|
|
@ -247,9 +247,9 @@ func (c *Client) upgradeRelease(
|
|||
) error {
|
||||
// We need to load all values that can be statically loaded before merging them with the cluster
|
||||
// values. Otherwise the templates are not rendered correctly.
|
||||
k8sVersion, err := versions.NewValidK8sVersion(conf.KubernetesVersion)
|
||||
k8sVersion, err := versions.NewValidK8sVersion(conf.KubernetesVersion, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid k8s version: %w", err)
|
||||
return fmt.Errorf("validating k8s version: %s", conf.KubernetesVersion)
|
||||
}
|
||||
loader := NewLoader(conf.GetProvider(), k8sVersion)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
|
||||
|
@ -178,12 +179,6 @@ func (u *Upgrader) UpgradeNodeVersion(ctx context.Context, conf *config.Config)
|
|||
return fmt.Errorf("parsing version from image short path: %w", err)
|
||||
}
|
||||
|
||||
currentK8sVersion, err := versions.NewValidK8sVersion(conf.KubernetesVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting Kubernetes version: %w", err)
|
||||
}
|
||||
versionConfig := versions.VersionConfigs[currentK8sVersion]
|
||||
|
||||
nodeVersion, err := u.checkClusterStatus(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -199,7 +194,18 @@ func (u *Upgrader) UpgradeNodeVersion(ctx context.Context, conf *config.Config)
|
|||
return fmt.Errorf("updating image version: %w", err)
|
||||
}
|
||||
|
||||
components, err := u.updateK8s(&nodeVersion, versionConfig.ClusterVersion, versionConfig.KubernetesComponents)
|
||||
// We have to allow users to specify outdated k8s patch versions.
|
||||
// Therefore, this code has to skip k8s updates if a user configures an outdated (i.e. invalid) k8s version.
|
||||
var components *corev1.ConfigMap
|
||||
currentK8sVersion, err := versions.NewValidK8sVersion(conf.KubernetesVersion, true)
|
||||
if err != nil {
|
||||
innerErr := fmt.Errorf("unsupported Kubernetes version, supported versions are %s", strings.Join(versions.SupportedK8sVersions(), ", "))
|
||||
err = compatibility.NewInvalidUpgradeError(nodeVersion.Spec.KubernetesClusterVersion, conf.KubernetesVersion, innerErr)
|
||||
} else {
|
||||
versionConfig := versions.VersionConfigs[currentK8sVersion]
|
||||
components, err = u.updateK8s(&nodeVersion, versionConfig.ClusterVersion, versionConfig.KubernetesComponents)
|
||||
}
|
||||
|
||||
switch {
|
||||
case err == nil:
|
||||
err := u.applyComponentsCM(ctx, components)
|
||||
|
|
|
@ -195,6 +195,27 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||
return assert.ErrorAs(t, err, &target)
|
||||
},
|
||||
},
|
||||
"outdated k8s version skips k8s upgrade": {
|
||||
conf: func() *config.Config {
|
||||
conf := config.Default()
|
||||
conf.Image = "v1.2.2"
|
||||
conf.KubernetesVersion = "v1.25.8"
|
||||
return conf
|
||||
}(),
|
||||
currentImageVersion: "v1.2.2",
|
||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
||||
stable: &stubStableClient{
|
||||
configMaps: map[string]*corev1.ConfigMap{
|
||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||
},
|
||||
},
|
||||
wantUpdate: false,
|
||||
wantErr: true,
|
||||
assertCorrectError: func(t *testing.T, err error) bool {
|
||||
var upgradeErr *compatibility.InvalidUpgradeError
|
||||
return assert.ErrorAs(t, err, &upgradeErr)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue