@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414limitations under the License.
1515*/
1616
17- package controller
17+ package appwrapper
1818
1919import (
2020 "context"
@@ -36,27 +36,26 @@ import (
3636 "sigs.k8s.io/controller-runtime/pkg/log"
3737 "sigs.k8s.io/controller-runtime/pkg/reconcile"
3838
39- kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
4039 "sigs.k8s.io/kueue/pkg/controller/constants"
41- "sigs.k8s.io/kueue/pkg/controller/jobframework"
4240 "sigs.k8s.io/kueue/pkg/podset"
4341 utilmaps "sigs.k8s.io/kueue/pkg/util/maps"
44- "sigs.k8s.io/kueue/pkg/workload"
4542
4643 workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
44+ "github.com/project-codeflare/appwrapper/internal/config"
45+ "github.com/project-codeflare/appwrapper/internal/utils"
4746)
4847
4948const (
5049 AppWrapperLabel = "workload.codeflare.dev/appwrapper"
51- appWrapperFinalizer = "workload.codeflare.dev/finalizer"
50+ AppWrapperFinalizer = "workload.codeflare.dev/finalizer"
5251 childJobQueueName = "workload.codeflare.dev.admitted"
5352)
5453
5554// AppWrapperReconciler reconciles an appwrapper
5655type AppWrapperReconciler struct {
5756 client.Client
5857 Scheme * runtime.Scheme
59- Config * AppWrapperConfig
58+ Config * config. AppWrapperConfig
6059}
6160
6261type podStatusSummary struct {
@@ -72,10 +71,6 @@ type podStatusSummary struct {
7271//+kubebuilder:rbac:groups=workload.codeflare.dev,resources=appwrappers/status,verbs=get;update;patch
7372//+kubebuilder:rbac:groups=workload.codeflare.dev,resources=appwrappers/finalizers,verbs=update
7473
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-
7974// permission to edit wrapped resources: pods, services, jobs, podgroups, pytorchjobs, rayclusters
8075
8176//+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)
10095
10196 // handle deletion first
10297 if ! aw .DeletionTimestamp .IsZero () {
103- if controllerutil .ContainsFinalizer (aw , appWrapperFinalizer ) {
98+ if controllerutil .ContainsFinalizer (aw , AppWrapperFinalizer ) {
10499 statusUpdated := false
105100 if meta .IsStatusConditionTrue (aw .Status .Conditions , string (workloadv1beta2 .ResourcesDeployed )) {
106101 if ! r .deleteComponents (ctx , aw ) {
@@ -136,7 +131,7 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
136131 }
137132 }
138133
139- if controllerutil .RemoveFinalizer (aw , appWrapperFinalizer ) {
134+ if controllerutil .RemoveFinalizer (aw , AppWrapperFinalizer ) {
140135 if err := r .Update (ctx , aw ); err != nil {
141136 return ctrl.Result {}, err
142137 }
@@ -149,7 +144,7 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
149144 switch aw .Status .Phase {
150145
151146 case workloadv1beta2 .AppWrapperEmpty : // initial state, inject finalizer
152- if controllerutil .AddFinalizer (aw , appWrapperFinalizer ) {
147+ if controllerutil .AddFinalizer (aw , AppWrapperFinalizer ) {
153148 if err := r .Update (ctx , aw ); err != nil {
154149 return ctrl.Result {}, err
155150 }
@@ -224,7 +219,6 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
224219 })
225220 return ctrl.Result {RequeueAfter : time .Minute }, r .Status ().Update (ctx , aw )
226221 }
227- r .propagateAdmission (ctx , aw )
228222 meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
229223 Type : string (workloadv1beta2 .PodsReady ),
230224 Status : metav1 .ConditionFalse ,
@@ -339,7 +333,7 @@ func (r *AppWrapperReconciler) createComponent(ctx context.Context, aw *workload
339333 for podSetsIdx , podSet := range component .PodSets {
340334 toInject := component .PodSetInfos [podSetsIdx ]
341335
342- p , err := getRawTemplate (obj .UnstructuredContent (), podSet .Path )
336+ p , err := utils . GetRawTemplate (obj .UnstructuredContent (), podSet .Path )
343337 if err != nil {
344338 return nil , err , true // Should not happen, path validity is enforced by validateAppWrapperInvariants
345339 }
@@ -411,36 +405,6 @@ func (r *AppWrapperReconciler) createComponents(ctx context.Context, aw *workloa
411405 return nil , false
412406}
413407
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-
444408func (r * AppWrapperReconciler ) deleteComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) bool {
445409 // TODO forceful deletion: See https://github.com/project-codeflare/appwrapper/issues/36
446410 log := log .FromContext (ctx )
@@ -478,7 +442,7 @@ func (r *AppWrapperReconciler) workloadStatus(ctx context.Context, aw *workloadv
478442 client.MatchingLabels {AppWrapperLabel : aw .Name }); err != nil {
479443 return nil , err
480444 }
481- summary := & podStatusSummary {expected : ExpectedPodCount (aw )}
445+ summary := & podStatusSummary {expected : utils . ExpectedPodCount (aw )}
482446
483447 for _ , pod := range pods .Items {
484448 switch pod .Status .Phase {
@@ -496,24 +460,6 @@ func (r *AppWrapperReconciler) workloadStatus(ctx context.Context, aw *workloadv
496460 return summary , nil
497461}
498462
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-
517463// SetupWithManager sets up the controller with the Manager.
518464func (r * AppWrapperReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
519465 return ctrl .NewControllerManagedBy (mgr ).
0 commit comments