mirror of
https://github.com/outbackdingo/cozystack.git
synced 2026-01-28 18:18:41 +00:00
Workloads tracking an object undergoing deletion can be reconciled when
the object is marked for deletion, but is not yet removed. After the
object is deleted, there is no event to trigger another reconciliation
of the workload and it might never get deleted until a global reconcile
happens or the controller is restarted. This patch ensures they are
requeued in the reconciliation loop.
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->
## What this PR does
### Release note
<!-- Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->
```release-note
[platform] Fix stale workloads not being deleted
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Improvements**
* Added a delay before reprocessing items that are being deleted,
resulting in more efficient handling of deletions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
(cherry picked from commit 7abca1bdf5)
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
|
|
|
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
|
)
|
|
|
|
const (
|
|
deletionRequeueDelay = 30 * time.Second
|
|
)
|
|
|
|
// WorkloadMonitorReconciler reconciles a WorkloadMonitor object
|
|
type WorkloadReconciler struct {
|
|
client.Client
|
|
Scheme *runtime.Scheme
|
|
}
|
|
|
|
func (r *WorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
|
logger := log.FromContext(ctx)
|
|
w := &cozyv1alpha1.Workload{}
|
|
err := r.Get(ctx, req.NamespacedName, w)
|
|
if err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
logger.Error(err, "Unable to fetch Workload")
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// it's being deleted, nothing to handle
|
|
if w.DeletionTimestamp != nil {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
t := getMonitoredObject(w)
|
|
|
|
if t == nil {
|
|
err = r.Delete(ctx, w)
|
|
if err != nil {
|
|
logger.Error(err, "failed to delete workload")
|
|
}
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
err = r.Get(ctx, types.NamespacedName{Name: t.GetName(), Namespace: t.GetNamespace()}, t)
|
|
|
|
// found object, nothing to do
|
|
if err == nil {
|
|
if !t.GetDeletionTimestamp().IsZero() {
|
|
return ctrl.Result{RequeueAfter: deletionRequeueDelay}, nil
|
|
}
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
// error getting object but not 404 -- requeue
|
|
if !apierrors.IsNotFound(err) {
|
|
logger.Error(err, "failed to get dependent object", "kind", t.GetObjectKind(), "dependent-object-name", t.GetName())
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
err = r.Delete(ctx, w)
|
|
if err != nil {
|
|
logger.Error(err, "failed to delete workload")
|
|
}
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// SetupWithManager registers our controller with the Manager and sets up watches.
|
|
func (r *WorkloadReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|
return ctrl.NewControllerManagedBy(mgr).
|
|
// Watch WorkloadMonitor objects
|
|
For(&cozyv1alpha1.Workload{}).
|
|
Complete(r)
|
|
}
|
|
|
|
func getMonitoredObject(w *cozyv1alpha1.Workload) client.Object {
|
|
switch {
|
|
case strings.HasPrefix(w.Name, "pvc-"):
|
|
obj := &corev1.PersistentVolumeClaim{}
|
|
obj.Name = strings.TrimPrefix(w.Name, "pvc-")
|
|
obj.Namespace = w.Namespace
|
|
return obj
|
|
case strings.HasPrefix(w.Name, "svc-"):
|
|
obj := &corev1.Service{}
|
|
obj.Name = strings.TrimPrefix(w.Name, "svc-")
|
|
obj.Namespace = w.Namespace
|
|
return obj
|
|
case strings.HasPrefix(w.Name, "pod-"):
|
|
obj := &corev1.Pod{}
|
|
obj.Name = strings.TrimPrefix(w.Name, "pod-")
|
|
obj.Namespace = w.Namespace
|
|
return obj
|
|
}
|
|
var obj client.Object
|
|
return obj
|
|
}
|