Skip to content

Commit 5884c4a

Browse files
VSphere failure domain delete cluster bug fix (#9556)
* deletion bug fix * added failure domain mover tests * formatting
1 parent 151e553 commit 5884c4a

File tree

5 files changed

+778
-29
lines changed

5 files changed

+778
-29
lines changed

controllers/cluster_controller.go

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ import (
2727
"github.com/aws/eks-anywhere/pkg/controller/clientutil"
2828
"github.com/aws/eks-anywhere/pkg/controller/clusters"
2929
"github.com/aws/eks-anywhere/pkg/controller/handlers"
30+
"github.com/aws/eks-anywhere/pkg/controller/serverside"
3031
"github.com/aws/eks-anywhere/pkg/curatedpackages"
32+
"github.com/aws/eks-anywhere/pkg/features"
33+
"github.com/aws/eks-anywhere/pkg/providers/vsphere"
3134
"github.com/aws/eks-anywhere/pkg/registrymirror"
3235
"github.com/aws/eks-anywhere/pkg/utils/ptr"
3336
"github.com/aws/eks-anywhere/pkg/validations"
@@ -49,6 +52,7 @@ type ClusterReconciler struct {
4952
clusterValidator ClusterValidator
5053
packagesClient PackagesClient
5154
machineHealthCheck MachineHealthCheckReconciler
55+
vSpherefailureDomainMover FailureDomainApplier
5256
}
5357

5458
// PackagesClient handles curated packages operations from within the cluster
@@ -83,15 +87,93 @@ type ClusterValidator interface {
8387
// ClusterReconcilerOption allows to configure the ClusterReconciler.
8488
type ClusterReconcilerOption func(*ClusterReconciler)
8589

90+
// SpecBuilder builds a cluster specification from an EKS Anywhere Cluster object.
91+
type SpecBuilder interface {
92+
BuildSpec(ctx context.Context, eksaCluster *anywherev1.Cluster) (*c.Spec, error)
93+
}
94+
95+
// FailureDomainSpecBuilder transforms a cluster specification into VSphere-specific failure domains.
96+
type FailureDomainSpecBuilder interface {
97+
BuildFailureDomainSpec(log logr.Logger, clusterSpec *c.Spec) (*vsphere.FailureDomains, error)
98+
}
99+
100+
// ObjectReconciler applies failure domain objects to a Kubernetes cluster.
101+
type ObjectReconciler interface {
102+
ReconcileObjects(ctx context.Context, fd *vsphere.FailureDomains) error
103+
}
104+
105+
// FailureDomainApplier orchestrates the end-to-end process of applying failure domains to a cluster.
106+
type FailureDomainApplier interface {
107+
ApplyFailureDomains(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) error
108+
}
109+
110+
// DefaultSpecBuilder is the standard implementation of SpecBuilder that uses a Kubernetes client.
111+
type DefaultSpecBuilder struct {
112+
client client.Client
113+
}
114+
115+
// BuildSpec is a wrapper method for building and obtaining all neccessary objects from a cluster.
116+
func (b *DefaultSpecBuilder) BuildSpec(ctx context.Context, cluster *anywherev1.Cluster) (*c.Spec, error) {
117+
return c.BuildSpec(ctx, clientutil.NewKubeClient(b.client), cluster)
118+
}
119+
120+
// DefaultFailureDomainSpecBuilder is the standard implementation of FailureDomainSpecBuilder.
121+
type DefaultFailureDomainSpecBuilder struct{}
122+
123+
// BuildFailureDomainSpec wrapper to the vsphere package's FailureDomainsSpec function.
124+
func (b *DefaultFailureDomainSpecBuilder) BuildFailureDomainSpec(log logr.Logger, clusterSpec *c.Spec) (*vsphere.FailureDomains, error) {
125+
return vsphere.FailureDomainsSpec(log, clusterSpec)
126+
}
127+
128+
// DefaultObjectReconciler is the standard implementation of ObjectReconciler that applies objects using a client.
129+
type DefaultObjectReconciler struct {
130+
client client.Client
131+
}
132+
133+
// ReconcileObjects applies failure domain objects to the cluster using serverside reconciliation.
134+
func (r *DefaultObjectReconciler) ReconcileObjects(ctx context.Context, fd *vsphere.FailureDomains) error {
135+
return serverside.ReconcileObjects(ctx, r.client, fd.Objects())
136+
}
137+
138+
// FailureDomainMover defines config for applying failure domain objects.
139+
type FailureDomainMover struct {
140+
specBuilder SpecBuilder
141+
fdSpecBuilder FailureDomainSpecBuilder
142+
objectReconciler ObjectReconciler
143+
}
144+
145+
// NewFailureDomainMover builds FailureDomainMover with default dependencies.
146+
func NewFailureDomainMover(client client.Client) *FailureDomainMover {
147+
return &FailureDomainMover{
148+
specBuilder: &DefaultSpecBuilder{client: client},
149+
fdSpecBuilder: &DefaultFailureDomainSpecBuilder{},
150+
objectReconciler: &DefaultObjectReconciler{client: client},
151+
}
152+
}
153+
154+
// NewFailureDomainMoverWithDependencies builds FailureDomainMover with specified dependencies.
155+
func NewFailureDomainMoverWithDependencies(
156+
specBuilder SpecBuilder,
157+
fdSpecBuilder FailureDomainSpecBuilder,
158+
objectReconciler ObjectReconciler,
159+
) *FailureDomainMover {
160+
return &FailureDomainMover{
161+
specBuilder: specBuilder,
162+
fdSpecBuilder: fdSpecBuilder,
163+
objectReconciler: objectReconciler,
164+
}
165+
}
166+
86167
// NewClusterReconciler constructs a new ClusterReconciler.
87-
func NewClusterReconciler(client client.Client, registry ProviderClusterReconcilerRegistry, awsIamAuth AWSIamConfigReconciler, clusterValidator ClusterValidator, pkgs PackagesClient, machineHealthCheck MachineHealthCheckReconciler, opts ...ClusterReconcilerOption) *ClusterReconciler {
168+
func NewClusterReconciler(client client.Client, registry ProviderClusterReconcilerRegistry, awsIamAuth AWSIamConfigReconciler, clusterValidator ClusterValidator, pkgs PackagesClient, machineHealthCheck MachineHealthCheckReconciler, failuredomainmover FailureDomainApplier, opts ...ClusterReconcilerOption) *ClusterReconciler {
88169
c := &ClusterReconciler{
89170
client: client,
90171
providerReconcilerRegistry: registry,
91172
awsIamAuth: awsIamAuth,
92173
clusterValidator: clusterValidator,
93174
packagesClient: pkgs,
94175
machineHealthCheck: machineHealthCheck,
176+
vSpherefailureDomainMover: failuredomainmover,
95177
}
96178

97179
for _, opt := range opts {
@@ -488,6 +570,18 @@ func (r *ClusterReconciler) reconcileDelete(ctx context.Context, log logr.Logger
488570
return ctrl.Result{}, nil
489571
}
490572

573+
// Creates vspheredeploymentzone and vspherefailuredomain CR on bootstrap cluster prior to delete
574+
// These CRs are not migrated over during pivot and must be present to cleanly delete vspheremachines
575+
// This solution isn't ideal, but would require redesign
576+
if cluster.Spec.DatacenterRef.Kind == "VSphereDatacenterConfig" && cluster.IsSelfManaged() {
577+
if features.IsActive(features.VsphereFailureDomainEnabled()) {
578+
log.Info("Creating vspheredeploymentzones and vspherefailuredomains on bootstrap")
579+
if err := r.applyFailureDomains(ctx, log, cluster); err != nil {
580+
return ctrl.Result{}, err
581+
}
582+
}
583+
}
584+
491585
capiCluster := &clusterv1.Cluster{}
492586
capiClusterName := types.NamespacedName{Namespace: constants.EksaSystemNamespace, Name: cluster.Name}
493587
log.Info("Deleting", "name", cluster.Name)
@@ -541,6 +635,25 @@ func (r *ClusterReconciler) buildClusterConfig(ctx context.Context, clus *anywhe
541635
return config, nil
542636
}
543637

638+
func (r *ClusterReconciler) applyFailureDomains(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) error {
639+
return r.vSpherefailureDomainMover.ApplyFailureDomains(ctx, log, cluster)
640+
}
641+
642+
// ApplyFailureDomains orchestrates the end-to-end process of applying failure domain objects to a cluster.
643+
func (m *FailureDomainMover) ApplyFailureDomains(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) error {
644+
clusterSpec, err := m.specBuilder.BuildSpec(ctx, cluster)
645+
if err != nil {
646+
return err
647+
}
648+
649+
fd, err := m.fdSpecBuilder.BuildFailureDomainSpec(log, clusterSpec)
650+
if err != nil {
651+
return err
652+
}
653+
654+
return m.objectReconciler.ReconcileObjects(ctx, fd)
655+
}
656+
544657
func (r *ClusterReconciler) ensureClusterOwnerReferences(ctx context.Context, clus *anywherev1.Cluster, config *c.Config) error {
545658
for _, obj := range config.ChildObjects() {
546659
numberOfOwnerReferences := len(obj.GetOwnerReferences())

0 commit comments

Comments
 (0)