Skip to content

Commit b9378e7

Browse files
authored
bug fix in managedBy logic (#307)
defaulting webhooks can run in any order, therefore we can't rely using the value of managedBy seen by our defaulter to figure out whether or not we should add the appwrapper finalizer. To reduce reconciliation conflicts with Kueue, defer adding the finalizer until we are taking the Suspended to Resuming transition (which will only happen after Kueue's workload controller successfully updates Spec.Suspend).
1 parent c17a9bd commit b9378e7

File tree

3 files changed

+9
-38
lines changed

3 files changed

+9
-38
lines changed

internal/controller/appwrapper/appwrapper_controller.go

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,8 @@ import (
4040
"sigs.k8s.io/controller-runtime/pkg/handler"
4141
"sigs.k8s.io/controller-runtime/pkg/log"
4242
"sigs.k8s.io/controller-runtime/pkg/reconcile"
43-
"sigs.k8s.io/kueue/pkg/controller/jobframework"
44-
utilmaps "sigs.k8s.io/kueue/pkg/util/maps"
4543

4644
workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
47-
wlc "github.com/project-codeflare/appwrapper/internal/controller/workload"
4845
"github.com/project-codeflare/appwrapper/internal/metrics"
4946
"github.com/project-codeflare/appwrapper/pkg/config"
5047
"github.com/project-codeflare/appwrapper/pkg/utils"
@@ -162,30 +159,6 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
162159
switch aw.Status.Phase {
163160

164161
case workloadv1beta2.AppWrapperEmpty: // initial state
165-
if !controllerutil.ContainsFinalizer(aw, AppWrapperFinalizer) {
166-
// The AppWrapperFinalizer is added by our webhook, so if we get here it means that we are
167-
// running in dev mode (`make run`) which disables the webhook. To make dev mode as
168-
// useful as possible, replicate as much of AppWrapperWebhook.Default() as we can without having the admission.Request.
169-
if r.Config.EnableKueueIntegrations {
170-
if r.Config.DefaultQueueName != "" {
171-
aw.Labels = utilmaps.MergeKeepFirst(aw.Labels, map[string]string{"kueue.x-k8s.io/queue-name": r.Config.DefaultQueueName})
172-
}
173-
nsSelector, err := metav1.LabelSelectorAsSelector(r.Config.KueueJobReconciller.ManageJobsNamespaceSelector)
174-
if err != nil {
175-
return ctrl.Result{}, err
176-
}
177-
err = jobframework.ApplyDefaultForSuspend(ctx, (*wlc.AppWrapper)(aw), r.Client, r.Config.KueueJobReconciller.ManageJobsWithoutQueueName, nsSelector)
178-
if err != nil {
179-
return ctrl.Result{}, err
180-
}
181-
}
182-
controllerutil.AddFinalizer(aw, AppWrapperFinalizer)
183-
if err := r.Update(ctx, aw); err != nil {
184-
return ctrl.Result{}, err
185-
}
186-
log.FromContext(ctx).Info("No webhook: applied default initializations")
187-
}
188-
189162
orig := copyForStatusPatch(aw)
190163
if err := utils.EnsureComponentStatusInitialized(aw); err != nil {
191164
return ctrl.Result{}, err
@@ -198,6 +171,14 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
198171
return ctrl.Result{}, nil // remain suspended
199172
}
200173

174+
// ensure our finalizer is present before we deploy any resources
175+
if controllerutil.AddFinalizer(aw, AppWrapperFinalizer) {
176+
if err := r.Update(ctx, aw); err != nil {
177+
return ctrl.Result{}, err
178+
}
179+
log.FromContext(ctx).Info("Finalizer Added")
180+
}
181+
201182
// begin deployment
202183
orig := copyForStatusPatch(aw)
203184
meta.SetStatusCondition(&aw.Status.Conditions, metav1.Condition{

internal/controller/appwrapper/appwrapper_controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ var _ = Describe("AppWrapper Controller", func() {
8181

8282
aw = getAppWrapper(awName)
8383
Expect(aw.Status.Phase).Should(Equal(workloadv1beta2.AppWrapperSuspended))
84-
Expect(controllerutil.ContainsFinalizer(aw, AppWrapperFinalizer)).Should(BeTrue())
8584

8685
By("Updating aw.Spec by invoking RunWithPodSetsInfo")
8786
Expect((*workload.AppWrapper)(aw).RunWithPodSetsInfo([]podset.PodSetInfo{markerPodSet, markerPodSet})).To(Succeed())
@@ -94,6 +93,7 @@ var _ = Describe("AppWrapper Controller", func() {
9493

9594
aw = getAppWrapper(awName)
9695
Expect(aw.Status.Phase).Should(Equal(workloadv1beta2.AppWrapperResuming))
96+
Expect(controllerutil.ContainsFinalizer(aw, AppWrapperFinalizer)).Should(BeTrue())
9797
Expect(meta.IsStatusConditionTrue(aw.Status.Conditions, string(workloadv1beta2.ResourcesDeployed))).Should(BeTrue())
9898
Expect(meta.IsStatusConditionTrue(aw.Status.Conditions, string(workloadv1beta2.QuotaReserved))).Should(BeTrue())
9999
Expect((*workload.AppWrapper)(aw).IsActive()).Should(BeTrue())

internal/webhook/appwrapper_webhook.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,13 @@ import (
3535

3636
ctrl "sigs.k8s.io/controller-runtime"
3737
"sigs.k8s.io/controller-runtime/pkg/client"
38-
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3938
"sigs.k8s.io/controller-runtime/pkg/log"
4039
"sigs.k8s.io/controller-runtime/pkg/webhook"
4140
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
4241

4342
"sigs.k8s.io/kueue/pkg/controller/jobframework"
4443

4544
workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
46-
awc "github.com/project-codeflare/appwrapper/internal/controller/appwrapper"
4745
wlc "github.com/project-codeflare/appwrapper/internal/controller/workload"
4846
"github.com/project-codeflare/appwrapper/pkg/config"
4947
"github.com/project-codeflare/appwrapper/pkg/utils"
@@ -105,14 +103,6 @@ func (w *appWrapperWebhook) Default(ctx context.Context, obj runtime.Object) err
105103
username := utils.SanitizeLabel(userInfo.Username)
106104
aw.Labels = utilmaps.MergeKeepFirst(map[string]string{AppWrapperUsernameLabel: username, AppWrapperUserIDLabel: userInfo.UID}, aw.Labels)
107105

108-
// do not inject finalizer if managed by another controller
109-
if aw.Spec.ManagedBy != nil && *aw.Spec.ManagedBy != workloadv1beta2.AppWrapperControllerName {
110-
return nil
111-
}
112-
113-
// inject finalizer now (avoid reconcilier errors between the AppWrapper and WorkloadControllers when it is admitted by a ClusterQueue almost immediately)
114-
controllerutil.AddFinalizer(aw, awc.AppWrapperFinalizer)
115-
116106
return nil
117107
}
118108

0 commit comments

Comments
 (0)