@@ -34,8 +34,8 @@ import (
34
34
"sigs.k8s.io/controller-runtime/pkg/handler"
35
35
"sigs.k8s.io/controller-runtime/pkg/log"
36
36
"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 "
39
39
40
40
workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
41
41
)
@@ -299,38 +299,98 @@ func parseComponent(aw *workloadv1beta2.AppWrapper, raw []byte) (*unstructured.U
299
299
return obj , nil
300
300
}
301
301
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
+ }
309
323
}
310
- objects [i ] = obj
311
324
}
312
- return objects , nil
313
- }
325
+ awLabels := map [string ]string {AppWrapperLabel : aw .Name }
314
326
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 )
317
328
if err != nil {
318
- return err , true // fatal
329
+ return nil , err
319
330
}
320
331
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
+ }
325
382
}
326
383
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
331
392
}
332
- annotations [constants .ParentWorkloadAnnotation ] = myWorkloadName
333
- obj .SetAnnotations (annotations )
393
+
334
394
if err := controllerutil .SetControllerReference (aw , obj , r .Scheme ); err != nil {
335
395
return err , true
336
396
}
0 commit comments