Skip to content

Commit 4d5d744

Browse files
Bohdan Siryktestisnullus
Bohdan Siryk
authored andcommitted
issue-572-2, handling of external deletion for clusterresources was implemented
1 parent 5c49b62 commit 4d5d744

16 files changed

+343
-14
lines changed

apis/clusterresources/v1beta1/awsencryptionkey_types.go

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type AWSEncryptionKeySpec struct {
3434
type AWSEncryptionKeyStatus struct {
3535
ID string `json:"id,omitempty"`
3636
InUse bool `json:"inUse,omitempty"`
37+
State string `json:"state,omitempty"`
3738
}
3839

3940
//+kubebuilder:object:root=true

apis/clusterresources/v1beta1/awsendpointserviceprincipal_types.go

+7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ type AWSEndpointServicePrincipalStatus struct {
4040

4141
// The Instaclustr ID of the AWS endpoint service
4242
EndPointServiceID string `json:"endPointServiceId,omitempty"`
43+
44+
// State describe current state of the resource
45+
State string `json:"state,omitempty"`
4346
}
4447

4548
//+kubebuilder:object:root=true
@@ -58,6 +61,10 @@ func (r *AWSEndpointServicePrincipal) NewPatch() client.Patch {
5861
return client.MergeFrom(r.DeepCopy())
5962
}
6063

64+
func (r *AWSEndpointServicePrincipal) GetJobID(job string) string {
65+
return r.Namespace + "/" + r.Name + "/" + job
66+
}
67+
6168
//+kubebuilder:object:root=true
6269

6370
// AWSEndpointServicePrincipalList contains a list of AWSEndpointServicePrincipal

config/crd/bases/clusterresources.instaclustr.com_awsencryptionkeys.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ spec:
5252
type: string
5353
inUse:
5454
type: boolean
55+
state:
56+
type: string
5557
type: object
5658
type: object
5759
served: true

config/crd/bases/clusterresources.instaclustr.com_awsendpointserviceprincipals.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ spec:
6060
id:
6161
description: The Instaclustr ID of the IAM Principal ARN
6262
type: string
63+
state:
64+
description: State describe current state of the resource
65+
type: string
6366
type: object
6467
type: object
6568
served: true

controllers/clusterresources/awsencryptionkey_controller.go

+42-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ func (r *AWSEncryptionKeyReconciler) handleCreate(
129129
)
130130

131131
encryptionKey.Status = *encryptionKeyStatus
132+
encryptionKey.Status.State = models.CreatedStatus
132133
err = r.Status().Patch(ctx, encryptionKey, patch)
133134
if err != nil {
134135
l.Error(err, "Cannot patch AWS encryption key status ", "ID", encryptionKey.Status.ID)
@@ -274,8 +275,30 @@ func (r *AWSEncryptionKeyReconciler) startEncryptionKeyStatusJob(encryptionKey *
274275
func (r *AWSEncryptionKeyReconciler) newWatchStatusJob(encryptionKey *v1beta1.AWSEncryptionKey) scheduler.Job {
275276
l := log.Log.WithValues("component", "EncryptionKeyStatusJob")
276277
return func() error {
278+
ctx := context.Background()
279+
280+
key := client.ObjectKeyFromObject(encryptionKey)
281+
err := r.Get(ctx, key, encryptionKey)
282+
if err != nil {
283+
if k8serrors.IsNotFound(err) {
284+
l.Info("Resource is not found in the k8s cluster. Closing Instaclustr status sync.",
285+
"namespaced name", key,
286+
)
287+
288+
r.Scheduler.RemoveJob(encryptionKey.GetJobID(scheduler.StatusChecker))
289+
290+
return nil
291+
}
292+
293+
return err
294+
}
295+
277296
instaEncryptionKeyStatus, err := r.API.GetEncryptionKeyStatus(encryptionKey.Status.ID, instaclustr.AWSEncryptionKeyEndpoint)
278297
if err != nil {
298+
if errors.Is(err, instaclustr.NotFound) {
299+
return r.handleExternalDelete(ctx, encryptionKey)
300+
}
301+
279302
l.Error(err, "Cannot get AWS encryption key status from Inst API", "encryption key ID", encryptionKey.Status.ID)
280303
return err
281304
}
@@ -286,7 +309,7 @@ func (r *AWSEncryptionKeyReconciler) newWatchStatusJob(encryptionKey *v1beta1.AW
286309
"encryption key status", encryptionKey.Status)
287310
patch := encryptionKey.NewPatch()
288311
encryptionKey.Status = *instaEncryptionKeyStatus
289-
err := r.Status().Patch(context.Background(), encryptionKey, patch)
312+
err := r.Status().Patch(ctx, encryptionKey, patch)
290313
if err != nil {
291314
return err
292315
}
@@ -296,6 +319,24 @@ func (r *AWSEncryptionKeyReconciler) newWatchStatusJob(encryptionKey *v1beta1.AW
296319
}
297320
}
298321

322+
func (r *AWSEncryptionKeyReconciler) handleExternalDelete(ctx context.Context, key *v1beta1.AWSEncryptionKey) error {
323+
l := log.FromContext(ctx)
324+
325+
patch := key.NewPatch()
326+
key.Status.State = models.DeletedStatus
327+
err := r.Status().Patch(ctx, key, patch)
328+
if err != nil {
329+
return err
330+
}
331+
332+
l.Info(instaclustr.MsgInstaclustrResourceNotFound)
333+
r.EventRecorder.Eventf(key, models.Warning, models.ExternalDeleted, instaclustr.MsgInstaclustrResourceNotFound)
334+
335+
r.Scheduler.RemoveJob(key.GetJobID(scheduler.StatusChecker))
336+
337+
return nil
338+
}
339+
299340
// SetupWithManager sets up the controller with the Manager.
300341
func (r *AWSEncryptionKeyReconciler) SetupWithManager(mgr ctrl.Manager) error {
301342
return ctrl.NewControllerManagedBy(mgr).

controllers/clusterresources/awsendpointserviceprincipal_controller.go

+69
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,19 @@ func (r *AWSEndpointServicePrincipalReconciler) handleCreate(ctx context.Context
144144
"AWS endpoint service principal resource has been created",
145145
)
146146

147+
err = r.startWatchStatusJob(ctx, principal)
148+
if err != nil {
149+
l.Error(err, "failed to start status checker job")
150+
r.EventRecorder.Eventf(principal, models.Warning, models.CreationFailed,
151+
"Failed to start status checker job. Reason: %w", err,
152+
)
153+
154+
return err
155+
}
156+
r.EventRecorder.Eventf(principal, models.Normal, models.Created,
157+
"Status check job %s has been started", principal.GetJobID(scheduler.StatusChecker),
158+
)
159+
147160
return nil
148161
}
149162

@@ -175,6 +188,62 @@ func (r *AWSEndpointServicePrincipalReconciler) handleDelete(ctx context.Context
175188
return nil
176189
}
177190

191+
func (r *AWSEndpointServicePrincipalReconciler) startWatchStatusJob(ctx context.Context, resource *clusterresourcesv1beta1.AWSEndpointServicePrincipal) error {
192+
job := r.newWatchStatusJob(ctx, resource)
193+
return r.Scheduler.ScheduleJob(resource.GetJobID(scheduler.StatusChecker), scheduler.ClusterStatusInterval, job)
194+
}
195+
196+
func (r *AWSEndpointServicePrincipalReconciler) newWatchStatusJob(ctx context.Context, principal *clusterresourcesv1beta1.AWSEndpointServicePrincipal) scheduler.Job {
197+
l := log.FromContext(ctx, "components", "WatchStatusJob")
198+
199+
return func() error {
200+
key := client.ObjectKeyFromObject(principal)
201+
err := r.Get(ctx, key, principal)
202+
if err != nil {
203+
if k8serrors.IsNotFound(err) {
204+
l.Info("Resource is not found in the k8s cluster. Closing Instaclustr status sync.",
205+
"namespaced name", key,
206+
)
207+
208+
r.Scheduler.RemoveJob(principal.GetJobID(scheduler.StatusChecker))
209+
210+
return nil
211+
}
212+
213+
return err
214+
}
215+
216+
_, err = r.API.GetAWSEndpointServicePrincipal(principal.Status.ID)
217+
if err != nil {
218+
if errors.Is(err, instaclustr.NotFound) {
219+
return r.handleExternalDelete(ctx, principal)
220+
}
221+
222+
return err
223+
}
224+
225+
return nil
226+
}
227+
}
228+
229+
func (r *AWSEndpointServicePrincipalReconciler) handleExternalDelete(ctx context.Context, principal *clusterresourcesv1beta1.AWSEndpointServicePrincipal) error {
230+
l := log.FromContext(ctx)
231+
232+
patch := principal.NewPatch()
233+
principal.Status.State = models.DeletedStatus
234+
err := r.Status().Patch(ctx, principal, patch)
235+
if err != nil {
236+
return err
237+
}
238+
239+
l.Info(instaclustr.MsgInstaclustrResourceNotFound)
240+
r.EventRecorder.Eventf(principal, models.Warning, models.ExternalDeleted, instaclustr.MsgInstaclustrResourceNotFound)
241+
242+
r.Scheduler.RemoveJob(principal.GetJobID(scheduler.StatusChecker))
243+
244+
return nil
245+
}
246+
178247
// SetupWithManager sets up the controller with the Manager.
179248
func (r *AWSEndpointServicePrincipalReconciler) SetupWithManager(mgr ctrl.Manager) error {
180249
return ctrl.NewControllerManagedBy(mgr).

controllers/clusterresources/awssecuritygroupfirewallrule_controller.go

+36-6
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,27 @@ func (r *AWSSecurityGroupFirewallRuleReconciler) newWatchStatusJob(firewallRule
288288
l := log.Log.WithValues("component", "FirewallRuleStatusJob")
289289
return func() error {
290290
ctx := context.Background()
291+
292+
key := client.ObjectKeyFromObject(firewallRule)
293+
err := r.Get(ctx, key, firewallRule)
294+
if err != nil {
295+
if k8serrors.IsNotFound(err) {
296+
l.Info("Resource is not found in the k8s cluster. Closing Instaclustr status sync.",
297+
"namespaced name", key,
298+
)
299+
300+
r.Scheduler.RemoveJob(firewallRule.GetJobID(scheduler.StatusChecker))
301+
302+
return nil
303+
}
304+
305+
return err
306+
}
307+
291308
instaFirewallRuleStatus, err := r.API.GetFirewallRuleStatus(firewallRule.Status.ID, instaclustr.AWSSecurityGroupFirewallRuleEndpoint)
292309
if err != nil {
293310
if errors.Is(err, instaclustr.NotFound) {
294-
l.Info("The resource has been deleted on Instaclustr, deleting resource in k8s...")
295-
return r.Delete(ctx, firewallRule)
311+
return r.handleExternalDelete(ctx, firewallRule)
296312
}
297313

298314
l.Error(err, "Cannot get AWS security group firewall rule status from Inst API", "firewall rule ID", firewallRule.Status.ID)
@@ -309,16 +325,30 @@ func (r *AWSSecurityGroupFirewallRuleReconciler) newWatchStatusJob(firewallRule
309325
if err != nil {
310326
return err
311327
}
312-
313-
if instaFirewallRuleStatus.Status == statusDELETED {
314-
r.Scheduler.RemoveJob(firewallRule.GetJobID(scheduler.StatusChecker))
315-
}
316328
}
317329

318330
return nil
319331
}
320332
}
321333

334+
func (r *AWSSecurityGroupFirewallRuleReconciler) handleExternalDelete(ctx context.Context, rule *v1beta1.AWSSecurityGroupFirewallRule) error {
335+
l := log.FromContext(ctx)
336+
337+
patch := rule.NewPatch()
338+
rule.Status.Status = models.DeletedStatus
339+
err := r.Status().Patch(ctx, rule, patch)
340+
if err != nil {
341+
return err
342+
}
343+
344+
l.Info(instaclustr.MsgInstaclustrResourceNotFound)
345+
r.EventRecorder.Eventf(rule, models.Warning, models.ExternalDeleted, instaclustr.MsgInstaclustrResourceNotFound)
346+
347+
r.Scheduler.RemoveJob(rule.GetJobID(scheduler.StatusChecker))
348+
349+
return nil
350+
}
351+
322352
// SetupWithManager sets up the controller with the Manager.
323353
func (r *AWSSecurityGroupFirewallRuleReconciler) SetupWithManager(mgr ctrl.Manager) error {
324354
return ctrl.NewControllerManagedBy(mgr).

controllers/clusterresources/awsvpcpeering_controller.go

+32-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
k8serrors "k8s.io/apimachinery/pkg/api/errors"
2525
"k8s.io/apimachinery/pkg/runtime"
2626
"k8s.io/client-go/tools/record"
27-
"k8s.io/utils/strings/slices"
2827
ctrl "sigs.k8s.io/controller-runtime"
2928
"sigs.k8s.io/controller-runtime/pkg/builder"
3029
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -208,7 +207,7 @@ func (r *AWSVPCPeeringReconciler) handleUpdatePeering(
208207
}
209208

210209
if aws.Annotations[models.ExternalChangesAnnotation] == models.True {
211-
if !slices.Equal(instaAWSPeering.PeerSubnets, aws.Spec.PeerSubnets) {
210+
if !subnetsEqual(instaAWSPeering.PeerSubnets, aws.Spec.PeerSubnets) {
212211
l.Info("The resource specification still differs from the Instaclustr resource specification, please reconcile it manually",
213212
"AWS VPC ID", aws.Status.ID,
214213
"k8s peerSubnets", aws.Spec.PeerSubnets,
@@ -404,8 +403,7 @@ func (r *AWSVPCPeeringReconciler) newWatchStatusJob(awsPeering *v1beta1.AWSVPCPe
404403
instaAWSPeering, err := r.API.GetAWSVPCPeering(awsPeering.Status.ID)
405404
if err != nil {
406405
if errors.Is(err, instaclustr.NotFound) {
407-
l.Info("The resource has been deleted on Instaclustr, deleting resource in k8s...")
408-
return r.Delete(ctx, awsPeering)
406+
return r.handleExternalDelete(ctx, awsPeering)
409407
}
410408

411409
l.Error(err, "cannot get AWS VPC Peering Status from Inst API",
@@ -432,9 +430,20 @@ func (r *AWSVPCPeeringReconciler) newWatchStatusJob(awsPeering *v1beta1.AWSVPCPe
432430
}
433431
}
434432

433+
if awsPeering.Status.StatusCode == models.AWSVPCPeeringStatusCodeDeleted {
434+
l.Info("The AWSPeering was deleted on AWS, stopping job...")
435+
r.EventRecorder.Event(awsPeering, models.Warning, models.DeletedEvent,
436+
"The AWSPeering was deleted on AWS, stopping job...",
437+
)
438+
439+
r.Scheduler.RemoveJob(awsPeering.GetJobID(scheduler.StatusChecker))
440+
441+
return nil
442+
}
443+
435444
if awsPeering.Annotations[models.ResourceStateAnnotation] != models.UpdatingEvent &&
436445
awsPeering.Annotations[models.ExternalChangesAnnotation] != models.True &&
437-
!slices.Equal(instaAWSPeering.PeerSubnets, awsPeering.Spec.PeerSubnets) {
446+
!subnetsEqual(instaAWSPeering.PeerSubnets, awsPeering.Spec.PeerSubnets) {
438447
l.Info("The k8s resource specification doesn't match the specification of Instaclustr, please change it manually",
439448
"k8s peerSubnets", instaAWSPeering.PeerSubnets,
440449
"instaclutr peerSubnets", awsPeering.Spec.PeerSubnets,
@@ -498,3 +507,21 @@ func (r *AWSVPCPeeringReconciler) SetupWithManager(mgr ctrl.Manager) error {
498507
},
499508
})).Complete(r)
500509
}
510+
511+
func (r *AWSVPCPeeringReconciler) handleExternalDelete(ctx context.Context, key *v1beta1.AWSVPCPeering) error {
512+
l := log.FromContext(ctx)
513+
514+
patch := key.NewPatch()
515+
key.Status.StatusCode = models.DeletedStatus
516+
err := r.Status().Patch(ctx, key, patch)
517+
if err != nil {
518+
return err
519+
}
520+
521+
l.Info(instaclustr.MsgInstaclustrResourceNotFound)
522+
r.EventRecorder.Eventf(key, models.Warning, models.ExternalDeleted, instaclustr.MsgInstaclustrResourceNotFound)
523+
524+
r.Scheduler.RemoveJob(key.GetJobID(scheduler.StatusChecker))
525+
526+
return nil
527+
}

0 commit comments

Comments
 (0)