@@ -34,8 +34,8 @@ import (
3434 "sigs.k8s.io/controller-runtime/pkg/handler"
3535 "sigs.k8s.io/controller-runtime/pkg/log"
3636 "sigs.k8s.io/controller-runtime/pkg/reconcile"
37- "sigs.k8s.io/kueue/pkg/controller/constants "
38- "sigs.k8s.io/kueue/pkg/controller/jobframework "
37+ "sigs.k8s.io/kueue/pkg/podset "
38+ utilmaps "sigs.k8s.io/kueue/pkg/util/maps "
3939
4040 workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
4141)
@@ -299,38 +299,98 @@ func parseComponent(aw *workloadv1beta2.AppWrapper, raw []byte) (*unstructured.U
299299 return obj , nil
300300}
301301
302- func parseComponents (aw * workloadv1beta2.AppWrapper ) ([]client.Object , error ) {
303- components := aw .Spec .Components
304- objects := make ([]client.Object , len (components ))
305- for i , component := range components {
306- obj , err := parseComponent (aw , component .Template .Raw )
307- if err != nil {
308- return nil , err
302+ func materializeObject (aw * workloadv1beta2.AppWrapper , component * workloadv1beta2.AppWrapperComponent ) (client.Object , error ) {
303+ toMap := func (x interface {}) map [string ]string {
304+ if x == nil {
305+ return nil
306+ } else {
307+ if sm , ok := x .(map [string ]string ); ok {
308+ return sm
309+ } else if im , ok := x .(map [string ]interface {}); ok {
310+ sm := make (map [string ]string , len (im ))
311+ for k , v := range im {
312+ str , ok := v .(string )
313+ if ok {
314+ sm [k ] = str
315+ } else {
316+ sm [k ] = fmt .Sprint (v )
317+ }
318+ }
319+ return sm
320+ } else {
321+ return nil
322+ }
309323 }
310- objects [i ] = obj
311324 }
312- return objects , nil
313- }
325+ awLabels := map [string ]string {AppWrapperLabel : aw .Name }
314326
315- func (r * AppWrapperReconciler ) createComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) (error , bool ) {
316- objects , err := parseComponents (aw )
327+ obj , err := parseComponent (aw , component .Template .Raw )
317328 if err != nil {
318- return err , true // fatal
329+ return nil , err
319330 }
320331
321- ref := & metav1.OwnerReference {APIVersion : GVK .GroupVersion ().String (), Kind : GVK .Kind , Name : aw .Name , UID : aw .UID }
322- myWorkloadName , err := jobframework .GetWorkloadNameForOwnerRef (ref )
323- if err != nil {
324- return err , true
332+ for podSetsIdx , podSet := range component .PodSets {
333+ toInject := component .PodSetInfos [podSetsIdx ]
334+
335+ p , err := getRawTemplate (obj .UnstructuredContent (), podSet .Path )
336+ if err != nil {
337+ return nil , err // Should not happen, path validity is enforced by validateAppWrapperInvariants
338+ }
339+ if md , ok := p ["metadata" ]; ! ok || md == nil {
340+ p ["metadata" ] = make (map [string ]interface {})
341+ }
342+ metadata := p ["metadata" ].(map [string ]interface {})
343+ spec := p ["spec" ].(map [string ]interface {}) // Must exist, enforced by validateAppWrapperInvariants
344+
345+ // Annotations
346+ if len (toInject .Annotations ) > 0 {
347+ existing := toMap (metadata ["annotations" ])
348+ if err := utilmaps .HaveConflict (existing , toInject .Annotations ); err != nil {
349+ return nil , podset .BadPodSetsUpdateError ("annotations" , err )
350+ }
351+ metadata ["annotations" ] = utilmaps .MergeKeepFirst (existing , toInject .Annotations )
352+ }
353+
354+ // Labels
355+ mergedLabels := utilmaps .MergeKeepFirst (toInject .Labels , awLabels )
356+ existing := toMap (metadata ["labels" ])
357+ if err := utilmaps .HaveConflict (existing , mergedLabels ); err != nil {
358+ return nil , podset .BadPodSetsUpdateError ("labels" , err )
359+ }
360+ metadata ["labels" ] = utilmaps .MergeKeepFirst (existing , mergedLabels )
361+
362+ // NodeSelectors
363+ if len (toInject .NodeSelector ) > 0 {
364+ existing := toMap (metadata ["nodeSelector" ])
365+ if err := utilmaps .HaveConflict (existing , toInject .NodeSelector ); err != nil {
366+ return nil , podset .BadPodSetsUpdateError ("nodeSelector" , err )
367+ }
368+ metadata ["nodeSelector" ] = utilmaps .MergeKeepFirst (existing , toInject .NodeSelector )
369+ }
370+
371+ // Tolerations
372+ if len (toInject .Tolerations ) > 0 {
373+ if _ , ok := spec ["tolerations" ]; ! ok {
374+ spec ["tolerations" ] = []interface {}{}
375+ }
376+ tolerations := spec ["tolerations" ].([]interface {})
377+ for _ , addition := range toInject .Tolerations {
378+ tolerations = append (tolerations , addition )
379+ }
380+ spec ["tolerations" ] = tolerations
381+ }
325382 }
326383
327- for _ , obj := range objects {
328- annotations := obj .GetAnnotations ()
329- if annotations == nil {
330- annotations = make (map [string ]string )
384+ return obj , nil
385+ }
386+
387+ func (r * AppWrapperReconciler ) createComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) (error , bool ) {
388+ for _ , component := range aw .Spec .Components {
389+ obj , err := materializeObject (aw , & component )
390+ if err != nil {
391+ return err , true
331392 }
332- annotations [constants .ParentWorkloadAnnotation ] = myWorkloadName
333- obj .SetAnnotations (annotations )
393+
334394 if err := controllerutil .SetControllerReference (aw , obj , r .Scheme ); err != nil {
335395 return err , true
336396 }
0 commit comments