@@ -26,6 +26,7 @@ import (
2626 "k8s.io/apimachinery/pkg/api/equality"
2727 k8errors "k8s.io/apimachinery/pkg/api/errors"
2828 "k8s.io/apimachinery/pkg/api/meta"
29+ "k8s.io/apimachinery/pkg/api/resource"
2930 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031 "k8s.io/apimachinery/pkg/runtime"
3132 "k8s.io/client-go/tools/record"
@@ -347,8 +348,71 @@ func ensureClaimIdentityLabels(labels map[string]string, claim *extensionsv1alph
347348 return labels
348349}
349350
351+ func applyWorkspaceResourceOverrides (container * corev1.Container , overrides * extensionsv1alpha1.WorkspaceResources ) {
352+ if overrides == nil {
353+ return
354+ }
355+ if container .Resources .Requests == nil {
356+ container .Resources .Requests = corev1.ResourceList {}
357+ }
358+ if container .Resources .Limits == nil {
359+ container .Resources .Limits = corev1.ResourceList {}
360+ }
361+ if overrides .CPUMillicores > 0 {
362+ qty := * resource .NewMilliQuantity (int64 (overrides .CPUMillicores ), resource .DecimalSI )
363+ container .Resources .Requests [corev1 .ResourceCPU ] = qty
364+ container .Resources .Limits [corev1 .ResourceCPU ] = qty
365+ }
366+ if overrides .MemoryMB > 0 {
367+ qty := * resource .NewQuantity (int64 (overrides .MemoryMB )* 1024 * 1024 , resource .BinarySI )
368+ container .Resources .Requests [corev1 .ResourceMemory ] = qty
369+ container .Resources .Limits [corev1 .ResourceMemory ] = qty
370+ }
371+ if overrides .DiskGB > 0 {
372+ qty := * resource .NewQuantity (int64 (overrides .DiskGB )* 1024 * 1024 * 1024 , resource .BinarySI )
373+ container .Resources .Requests [corev1 .ResourceEphemeralStorage ] = qty
374+ container .Resources .Limits [corev1 .ResourceEphemeralStorage ] = qty
375+ }
376+ }
377+
378+ func applyClaimWorkspaceResourcesToPodSpec (spec * corev1.PodSpec , claim * extensionsv1alpha1.SandboxClaim ) {
379+ if claim .Spec .WorkspaceResources == nil {
380+ return
381+ }
382+ for i := range spec .Containers {
383+ container := & spec .Containers [i ]
384+ if container .Name != "workspace" {
385+ continue
386+ }
387+ applyWorkspaceResourceOverrides (container , claim .Spec .WorkspaceResources )
388+ }
389+ }
390+
391+ func mergeTemplatePodMetadata (target * v1alpha1.PodMetadata , template v1alpha1.PodMetadata ) {
392+ if len (template .Labels ) > 0 {
393+ if target .Labels == nil {
394+ target .Labels = make (map [string ]string , len (template .Labels ))
395+ }
396+ for k , v := range template .Labels {
397+ if _ , exists := target .Labels [k ]; ! exists {
398+ target .Labels [k ] = v
399+ }
400+ }
401+ }
402+ if len (template .Annotations ) > 0 {
403+ if target .Annotations == nil {
404+ target .Annotations = make (map [string ]string , len (template .Annotations ))
405+ }
406+ for k , v := range template .Annotations {
407+ if _ , exists := target .Annotations [k ]; ! exists {
408+ target .Annotations [k ] = v
409+ }
410+ }
411+ }
412+ }
413+
350414// adoptSandboxFromCandidates picks the best candidate and transfers ownership to the claim.
351- func (r * SandboxClaimReconciler ) adoptSandboxFromCandidates (ctx context.Context , claim * extensionsv1alpha1.SandboxClaim , candidates []* v1alpha1.Sandbox ) (* v1alpha1.Sandbox , error ) {
415+ func (r * SandboxClaimReconciler ) adoptSandboxFromCandidates (ctx context.Context , claim * extensionsv1alpha1.SandboxClaim , template * extensionsv1alpha1. SandboxTemplate , candidates []* v1alpha1.Sandbox ) (* v1alpha1.Sandbox , error ) {
352416 log := log .FromContext (ctx )
353417
354418 // Sort: ready sandboxes first, then by creation time (oldest first)
@@ -410,9 +474,14 @@ func (r *SandboxClaimReconciler) adoptSandboxFromCandidates(ctx context.Context,
410474 adopted .Annotations [asmetrics .TraceContextAnnotation ] = tc
411475 }
412476
477+ if template != nil {
478+ mergeTemplatePodMetadata (& adopted .Spec .PodTemplate .ObjectMeta , template .Spec .PodTemplate .ObjectMeta )
479+ }
480+
413481 // Propagate claim identity labels for discovery and NetworkPolicy targeting
414482 adopted .Labels = ensureClaimIdentityLabels (adopted .Labels , claim )
415483 adopted .Spec .PodTemplate .ObjectMeta .Labels = ensureClaimIdentityLabels (adopted .Spec .PodTemplate .ObjectMeta .Labels , claim )
484+ applyClaimWorkspaceResourcesToPodSpec (& adopted .Spec .PodTemplate .Spec , claim )
416485
417486 // Update uses optimistic concurrency (resourceVersion) so concurrent
418487 // claims racing to adopt the same sandbox will conflict and retry.
@@ -487,6 +556,7 @@ func (r *SandboxClaimReconciler) createSandbox(ctx context.Context, claim *exten
487556 sandbox .Annotations [v1alpha1 .SandboxTemplateRefAnnotation ] = template .Name
488557
489558 template .Spec .PodTemplate .DeepCopyInto (& sandbox .Spec .PodTemplate )
559+ applyClaimWorkspaceResourcesToPodSpec (& sandbox .Spec .PodTemplate .Spec , claim )
490560 // TODO: this is a workaround, remove replica assignment related issue #202
491561 replicas := int32 (1 )
492562 sandbox .Spec .Replicas = & replicas
@@ -634,7 +704,12 @@ func (r *SandboxClaimReconciler) getOrCreateSandbox(ctx context.Context, claim *
634704
635705 // Try to adopt from warm pool
636706 if len (adoptionCandidates ) > 0 {
637- adopted , err := r .adoptSandboxFromCandidates (ctx , claim , adoptionCandidates )
707+ var template * extensionsv1alpha1.SandboxTemplate
708+ template , err := r .getTemplate (ctx , claim )
709+ if err != nil && ! k8errors .IsNotFound (err ) {
710+ return nil , err
711+ }
712+ adopted , err := r .adoptSandboxFromCandidates (ctx , claim , template , adoptionCandidates )
638713 if err != nil {
639714 return nil , err
640715 }
0 commit comments