Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix management component upgrades and upgrade plan with Cluster using unsupported Kubernetes versions #7612

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 118 additions & 4 deletions cmd/eksctl-anywhere/cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"strings"
"time"

"github.com/pkg/errors"
"github.com/spf13/pflag"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"

"github.com/aws/eks-anywhere/pkg/api/v1alpha1"
Expand All @@ -19,11 +21,13 @@ import (
"github.com/aws/eks-anywhere/pkg/dependencies"
"github.com/aws/eks-anywhere/pkg/files"
"github.com/aws/eks-anywhere/pkg/kubeconfig"
"github.com/aws/eks-anywhere/pkg/logger"
"github.com/aws/eks-anywhere/pkg/manifests"
"github.com/aws/eks-anywhere/pkg/manifests/bundles"
"github.com/aws/eks-anywhere/pkg/providers/cloudstack/decoder"
"github.com/aws/eks-anywhere/pkg/types"
"github.com/aws/eks-anywhere/pkg/validations"
"github.com/aws/eks-anywhere/pkg/version"
releasev1 "github.com/aws/eks-anywhere/release/api/v1alpha1"
)

const defaultTinkerbellNodeStartupTimeout = 20 * time.Minute
Expand Down Expand Up @@ -156,10 +160,120 @@ func newClusterSpec(options clusterOptions) (*cluster.Spec, error) {
return clusterSpec, nil
}

func markFlagHidden(flagSet *pflag.FlagSet, flagName string) {
if err := flagSet.MarkHidden(flagName); err != nil {
logger.V(5).Info("Warning: Failed to mark flag as hidden: " + flagName)
func getBundles(cliVersion version.Info, bundlesManifestURL string) (*releasev1.Bundles, error) {
reader := files.NewReader(files.WithEKSAUserAgent("cli", cliVersion.GitVersion))
manifestReader := manifests.NewReader(reader)
if bundlesManifestURL == "" {
return manifestReader.ReadBundlesForVersion(cliVersion.GitVersion)
}

return bundles.Read(reader, bundlesManifestURL)
}

func getEksaRelease(cliVersion version.Info) (*releasev1.EksARelease, error) {
reader := files.NewReader(files.WithEKSAUserAgent("cli", cliVersion.GitVersion))
manifestReader := manifests.NewReader(reader)
release, err := manifestReader.ReadReleaseForVersion(cliVersion.GitVersion)
if err != nil {
return nil, err
}

return release, nil
}

func getConfig(clusterConfigPath string, cliVersion version.Info) (*cluster.Config, error) {
reader := files.NewReader(files.WithEKSAUserAgent("cli", cliVersion.GitVersion))
yaml, err := reader.ReadFile(clusterConfigPath)
if err != nil {
return nil, errors.Wrapf(err, "reading cluster config file")
}

config, err := cluster.ParseConfig(yaml)
if err != nil {
return nil, errors.Wrapf(err, "parsing cluster config yaml")
}

return config, nil
}

// newBasicSpec creates a new cluster.Spec with the given Config, Bundles, and EKSARelease.
// This was created as a short term fix to management upgrades when the Cluster object is using an
// unsupported version of Kubernetes.
//
// When building the full cluster.Spec definition, we fetch the eksdReleases for
// the KubernetesVersions for all unique k8s versions specified in the Cluster for both CP and workers.
// If the Cluster object is using an unsupported version of Kubernetes, an error thrown
// because it does not exist in the Bundles file. This method allows to build a cluster.Spec without
// encountering this problem when performing only a management component upgrade.
func newBasicSpec(config *cluster.Config, bundles *releasev1.Bundles, eksaRelease *releasev1.EKSARelease) *cluster.Spec {
s := &cluster.Spec{}
s.Bundles = bundles
s.Config = config

s.EKSARelease = eksaRelease
return s
}

func readBasicClusterSpec(clusterConfigPath string, cliVersion version.Info, options clusterOptions) (*cluster.Spec, error) {
bundle, err := getBundles(cliVersion, options.bundlesOverride)
if err != nil {
return nil, err
}
bundle.Namespace = constants.EksaSystemNamespace

config, err := getConfig(clusterConfigPath, cliVersion)
if err != nil {
return nil, err
}

config.Cluster.Spec.BundlesRef = nil

configManager, err := cluster.NewDefaultConfigManager()
if err != nil {
return nil, err
}
if err = configManager.SetDefaults(config); err != nil {
return nil, err
}

release, err := getEksaRelease(cliVersion)
if err != nil {
return nil, err
}

releaseVersion := v1alpha1.EksaVersion(release.Version)
config.Cluster.Spec.EksaVersion = &releaseVersion
eksaRelease := &releasev1.EKSARelease{
TypeMeta: metav1.TypeMeta{
Kind: releasev1.EKSAReleaseKind,
APIVersion: releasev1.SchemeBuilder.GroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: releasev1.GenerateEKSAReleaseName(release.Version),
Namespace: constants.EksaSystemNamespace,
},
Spec: releasev1.EKSAReleaseSpec{
ReleaseDate: release.Date,
Version: release.Version,
GitCommit: release.GitCommit,
BundleManifestURL: release.BundleManifestUrl,
BundlesRef: releasev1.BundlesRef{
APIVersion: releasev1.GroupVersion.String(),
Name: bundle.Name,
Namespace: bundle.Namespace,
},
},
}

return newBasicSpec(config, bundle, eksaRelease), nil
}

func newBasicClusterSpec(options clusterOptions) (*cluster.Spec, error) {
clusterSpec, err := readBasicClusterSpec(options.fileName, version.Get(), options)
if err != nil {
return nil, fmt.Errorf("unable to get cluster config from file: %v", err)
}
return clusterSpec, nil
}

func buildCliConfig(clusterSpec *cluster.Spec) *config.CliConfig {
Expand Down
2 changes: 1 addition & 1 deletion cmd/eksctl-anywhere/cmd/upgrademanagementcomponents.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var upgradeManagementComponentsCmd = &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

clusterSpec, err := newClusterSpec(umco.clusterOptions)
clusterSpec, err := newBasicClusterSpec(umco.clusterOptions)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/eksctl-anywhere/cmd/upgradeplanmanagementcomponents.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (uc *upgradeClusterOptions) upgradePlanManagementComponents(ctx context.Con
return fmt.Errorf("common validations failed due to: %v", err)
}

newClusterSpec, err := newClusterSpec(uc.clusterOptions)
newClusterSpec, err := newBasicClusterSpec(uc.clusterOptions)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/dependencies/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ func (d *Dependencies) Close(ctx context.Context) error {

// ForSpec constructs a Factory using the bundle referenced by clusterSpec.
func ForSpec(clusterSpec *cluster.Spec) *Factory {
versionsBundle := clusterSpec.RootVersionsBundle()
eksaToolsImage := versionsBundle.Eksa.CliTools
managementComponents := cluster.ManagementComponentsFromBundles(clusterSpec.Bundles)
eksaToolsImage := managementComponents.Eksa.CliTools
return NewFactory().
UseExecutableImage(eksaToolsImage.VersionedImage()).
WithRegistryMirror(registrymirror.FromCluster(clusterSpec.Cluster)).
UseProxyConfiguration(clusterSpec.Cluster.ProxyConfiguration()).
WithWriterFolder(clusterSpec.Cluster.Name).
WithDiagnosticCollectorImage(versionsBundle.Eksa.DiagnosticCollector.VersionedImage())
WithDiagnosticCollectorImage(managementComponents.Eksa.DiagnosticCollector.VersionedImage())
}

// Factory helps initialization.
Expand Down
6 changes: 0 additions & 6 deletions pkg/eksd/upgrader.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ func NewUpgrader(client EksdInstallerClient, reader Reader, opts ...UpgraderOpt)

// Upgrade checks for EKS-D updates, and if there are updates the EKS-D CRDs in the cluster.
func (u *Upgrader) Upgrade(ctx context.Context, cluster *types.Cluster, currentSpec, newSpec *cluster.Spec) error {
logger.V(1).Info("Checking for EKS-D CRD updates")
changeDiff := ChangeDiff(currentSpec, newSpec)
if changeDiff == nil {
logger.V(1).Info("Nothing to update for EKS-D.")
return nil
}
logger.V(1).Info("Updating EKS-D CRDs")
if err := u.InstallEksdCRDs(ctx, newSpec, cluster); err != nil {
return fmt.Errorf("updating EKS-D crds from bundles %d to bundles %d: %v", currentSpec.Bundles.Spec.Number, newSpec.Bundles.Spec.Number, err)
Expand Down
13 changes: 0 additions & 13 deletions pkg/eksd/upgrader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,6 @@ func newUpgraderTest(t *testing.T) *upgraderTest {
}
}

func TestEksdUpgradeNoSelfManaged(t *testing.T) {
tt := newUpgraderTest(t)
tt.newSpec.Cluster.SetManagedBy("management-cluster")

tt.Expect(tt.eksdUpgrader.Upgrade(tt.ctx, tt.cluster, tt.currentSpec, tt.newSpec)).To(BeNil())
}

func TestEksdUpgradeNoChanges(t *testing.T) {
tt := newUpgraderTest(t)

tt.Expect(tt.eksdUpgrader.Upgrade(tt.ctx, tt.cluster, tt.currentSpec, tt.newSpec)).To(BeNil())
}

func TestEksdUpgradeSuccess(t *testing.T) {
tt := newUpgraderTest(t)

Expand Down
Loading