@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
- package controller
17
+ package appwrapper
18
18
19
19
import (
20
20
"context"
@@ -36,27 +36,26 @@ import (
36
36
"sigs.k8s.io/controller-runtime/pkg/log"
37
37
"sigs.k8s.io/controller-runtime/pkg/reconcile"
38
38
39
- kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
40
39
"sigs.k8s.io/kueue/pkg/controller/constants"
41
- "sigs.k8s.io/kueue/pkg/controller/jobframework"
42
40
"sigs.k8s.io/kueue/pkg/podset"
43
41
utilmaps "sigs.k8s.io/kueue/pkg/util/maps"
44
- "sigs.k8s.io/kueue/pkg/workload"
45
42
46
43
workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
44
+ "github.com/project-codeflare/appwrapper/internal/config"
45
+ "github.com/project-codeflare/appwrapper/internal/utils"
47
46
)
48
47
49
48
const (
50
49
AppWrapperLabel = "workload.codeflare.dev/appwrapper"
51
- appWrapperFinalizer = "workload.codeflare.dev/finalizer"
50
+ AppWrapperFinalizer = "workload.codeflare.dev/finalizer"
52
51
childJobQueueName = "workload.codeflare.dev.admitted"
53
52
)
54
53
55
54
// AppWrapperReconciler reconciles an appwrapper
56
55
type AppWrapperReconciler struct {
57
56
client.Client
58
57
Scheme * runtime.Scheme
59
- Config * AppWrapperConfig
58
+ Config * config. AppWrapperConfig
60
59
}
61
60
62
61
type podStatusSummary struct {
@@ -72,10 +71,6 @@ type podStatusSummary struct {
72
71
//+kubebuilder:rbac:groups=workload.codeflare.dev,resources=appwrappers/status,verbs=get;update;patch
73
72
//+kubebuilder:rbac:groups=workload.codeflare.dev,resources=appwrappers/finalizers,verbs=update
74
73
75
- // permission to manipulate workloads controlling appwrapper components to enable admitting them to our pseudo-clusterqueue
76
- // +kubebuilder:rbac:groups=kueue.x-k8s.io,resources=workloads,verbs=get
77
- // +kubebuilder:rbac:groups=kueue.x-k8s.io,resources=workloads/status,verbs=get;update;patch
78
-
79
74
// permission to edit wrapped resources: pods, services, jobs, podgroups, pytorchjobs, rayclusters
80
75
81
76
//+kubebuilder:rbac:groups="",resources=pods;services,verbs=get;list;watch;create;update;patch;delete
@@ -100,7 +95,7 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
100
95
101
96
// handle deletion first
102
97
if ! aw .DeletionTimestamp .IsZero () {
103
- if controllerutil .ContainsFinalizer (aw , appWrapperFinalizer ) {
98
+ if controllerutil .ContainsFinalizer (aw , AppWrapperFinalizer ) {
104
99
statusUpdated := false
105
100
if meta .IsStatusConditionTrue (aw .Status .Conditions , string (workloadv1beta2 .ResourcesDeployed )) {
106
101
if ! r .deleteComponents (ctx , aw ) {
@@ -136,7 +131,7 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
136
131
}
137
132
}
138
133
139
- if controllerutil .RemoveFinalizer (aw , appWrapperFinalizer ) {
134
+ if controllerutil .RemoveFinalizer (aw , AppWrapperFinalizer ) {
140
135
if err := r .Update (ctx , aw ); err != nil {
141
136
return ctrl.Result {}, err
142
137
}
@@ -149,7 +144,7 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
149
144
switch aw .Status .Phase {
150
145
151
146
case workloadv1beta2 .AppWrapperEmpty : // initial state, inject finalizer
152
- if controllerutil .AddFinalizer (aw , appWrapperFinalizer ) {
147
+ if controllerutil .AddFinalizer (aw , AppWrapperFinalizer ) {
153
148
if err := r .Update (ctx , aw ); err != nil {
154
149
return ctrl.Result {}, err
155
150
}
@@ -224,7 +219,6 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
224
219
})
225
220
return ctrl.Result {RequeueAfter : time .Minute }, r .Status ().Update (ctx , aw )
226
221
}
227
- r .propagateAdmission (ctx , aw )
228
222
meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
229
223
Type : string (workloadv1beta2 .PodsReady ),
230
224
Status : metav1 .ConditionFalse ,
@@ -339,7 +333,7 @@ func (r *AppWrapperReconciler) createComponent(ctx context.Context, aw *workload
339
333
for podSetsIdx , podSet := range component .PodSets {
340
334
toInject := component .PodSetInfos [podSetsIdx ]
341
335
342
- p , err := getRawTemplate (obj .UnstructuredContent (), podSet .Path )
336
+ p , err := utils . GetRawTemplate (obj .UnstructuredContent (), podSet .Path )
343
337
if err != nil {
344
338
return nil , err , true // Should not happen, path validity is enforced by validateAppWrapperInvariants
345
339
}
@@ -411,36 +405,6 @@ func (r *AppWrapperReconciler) createComponents(ctx context.Context, aw *workloa
411
405
return nil , false
412
406
}
413
407
414
- func (r * AppWrapperReconciler ) propagateAdmission (ctx context.Context , aw * workloadv1beta2.AppWrapper ) {
415
- for componentIdx , component := range aw .Spec .Components {
416
- if len (component .PodSets ) > 0 {
417
- obj , err := parseComponent (aw , component .Template .Raw )
418
- if err != nil {
419
- return
420
- }
421
- wlName := jobframework .GetWorkloadNameForOwnerWithGVK (obj .GetName (), obj .GroupVersionKind ())
422
- wl := & kueue.Workload {}
423
- if err := r .Client .Get (ctx , client.ObjectKey {Namespace : aw .Namespace , Name : wlName }, wl ); err == nil {
424
- if ! workload .IsAdmitted (wl ) {
425
- admission := kueue.Admission {
426
- ClusterQueue : childJobQueueName ,
427
- PodSetAssignments : make ([]kueue.PodSetAssignment , len (aw .Spec .Components [componentIdx ].PodSets )),
428
- }
429
- for i := range admission .PodSetAssignments {
430
- admission .PodSetAssignments [i ].Name = wl .Spec .PodSets [i ].Name
431
- }
432
- newWorkload := wl .DeepCopy ()
433
- workload .SetQuotaReservation (newWorkload , & admission )
434
- _ = workload .SyncAdmittedCondition (newWorkload )
435
- if err = workload .ApplyAdmissionStatus (ctx , r .Client , newWorkload , false ); err != nil {
436
- log .FromContext (ctx ).Error (err , "syncing admission" , "appwrapper" , aw , "componentIdx" , componentIdx , "workload" , wl , "newworkload" , newWorkload )
437
- }
438
- }
439
- }
440
- }
441
- }
442
- }
443
-
444
408
func (r * AppWrapperReconciler ) deleteComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) bool {
445
409
// TODO forceful deletion: See https://github.com/project-codeflare/appwrapper/issues/36
446
410
log := log .FromContext (ctx )
@@ -478,7 +442,7 @@ func (r *AppWrapperReconciler) workloadStatus(ctx context.Context, aw *workloadv
478
442
client.MatchingLabels {AppWrapperLabel : aw .Name }); err != nil {
479
443
return nil , err
480
444
}
481
- summary := & podStatusSummary {expected : ExpectedPodCount (aw )}
445
+ summary := & podStatusSummary {expected : utils . ExpectedPodCount (aw )}
482
446
483
447
for _ , pod := range pods .Items {
484
448
switch pod .Status .Phase {
@@ -496,24 +460,6 @@ func (r *AppWrapperReconciler) workloadStatus(ctx context.Context, aw *workloadv
496
460
return summary , nil
497
461
}
498
462
499
- func replicas (ps workloadv1beta2.AppWrapperPodSet ) int32 {
500
- if ps .Replicas == nil {
501
- return 1
502
- } else {
503
- return * ps .Replicas
504
- }
505
- }
506
-
507
- func ExpectedPodCount (aw * workloadv1beta2.AppWrapper ) int32 {
508
- var expected int32
509
- for _ , c := range aw .Spec .Components {
510
- for _ , s := range c .PodSets {
511
- expected += replicas (s )
512
- }
513
- }
514
- return expected
515
- }
516
-
517
463
// SetupWithManager sets up the controller with the Manager.
518
464
func (r * AppWrapperReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
519
465
return ctrl .NewControllerManagedBy (mgr ).
0 commit comments