Skip to content

Commit e68a2e3

Browse files
committed
fix: preserve pod template annotations during warm adoption
1 parent 9347f1d commit e68a2e3

4 files changed

Lines changed: 76 additions & 3 deletions

File tree

controllers/sandbox_controller.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@ func (r *SandboxReconciler) reconcilePod(ctx context.Context, sandbox *sandboxv1
424424
if pod.Labels == nil {
425425
pod.Labels = make(map[string]string)
426426
}
427+
if pod.Annotations == nil {
428+
pod.Annotations = make(map[string]string)
429+
}
427430
changed := false
428431
if pod.Labels[sandboxLabel] != nameHash {
429432
pod.Labels[sandboxLabel] = nameHash
@@ -436,6 +439,12 @@ func (r *SandboxReconciler) reconcilePod(ctx context.Context, sandbox *sandboxv1
436439
changed = true
437440
}
438441
}
442+
for k, v := range sandbox.Spec.PodTemplate.ObjectMeta.Annotations {
443+
if pod.Annotations[k] != v {
444+
pod.Annotations[k] = v
445+
changed = true
446+
}
447+
}
439448

440449
// Set controller reference if the pod is not controlled by anything.
441450
if controllerRef := metav1.GetControllerOf(pod); controllerRef == nil {

controllers/sandbox_controller_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,9 @@ func TestReconcilePod(t *testing.T) {
613613
"agents.x-k8s.io/sandbox-name-hash": nameHash,
614614
"custom-label": "label-val",
615615
},
616+
Annotations: map[string]string{
617+
"custom-annotation": "anno-val",
618+
},
616619
OwnerReferences: []metav1.OwnerReference{sandboxControllerRef(sandboxName)},
617620
},
618621
Spec: corev1.PodSpec{
@@ -685,7 +688,7 @@ func TestReconcilePod(t *testing.T) {
685688
wantPod: nil,
686689
},
687690
{
688-
name: "adopts existing pod via annotation - pod gets label and owner reference",
691+
name: "adopts existing pod via annotation - pod gets metadata and owner reference",
689692
initialObjs: []runtime.Object{
690693
&corev1.Pod{
691694
ObjectMeta: metav1.ObjectMeta{
@@ -713,6 +716,11 @@ func TestReconcilePod(t *testing.T) {
713716
Spec: sandboxv1alpha1.SandboxSpec{
714717
Replicas: ptr.To(int32(1)),
715718
PodTemplate: sandboxv1alpha1.PodTemplate{
719+
ObjectMeta: sandboxv1alpha1.PodMetadata{
720+
Annotations: map[string]string{
721+
"io.codewire.sh/workspace": "true",
722+
},
723+
},
716724
Spec: corev1.PodSpec{
717725
Containers: []corev1.Container{
718726
{
@@ -731,6 +739,9 @@ func TestReconcilePod(t *testing.T) {
731739
Labels: map[string]string{
732740
sandboxLabel: nameHash,
733741
},
742+
Annotations: map[string]string{
743+
"io.codewire.sh/workspace": "true",
744+
},
734745
OwnerReferences: []metav1.OwnerReference{sandboxControllerRef(sandboxName)},
735746
},
736747
Spec: corev1.PodSpec{
@@ -783,6 +794,9 @@ func TestReconcilePod(t *testing.T) {
783794
"agents.x-k8s.io/sandbox-name-hash": nameHash,
784795
"custom-label": "label-val",
785796
},
797+
Annotations: map[string]string{
798+
"custom-annotation": "anno-val",
799+
},
786800
// Should still have the original controller reference
787801
OwnerReferences: []metav1.OwnerReference{
788802
{

extensions/controllers/sandboxclaim_controller.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,32 @@ func applyClaimWorkspaceResourcesToPodSpec(spec *corev1.PodSpec, claim *extensio
379379
applyWorkspaceResourceOverrides(container, claim.Spec.WorkspaceResources)
380380
}
381381
}
382+
383+
func mergeTemplatePodMetadata(target *v1alpha1.PodMetadata, template v1alpha1.PodMetadata) {
384+
if len(template.Labels) > 0 {
385+
if target.Labels == nil {
386+
target.Labels = make(map[string]string, len(template.Labels))
387+
}
388+
for k, v := range template.Labels {
389+
if _, exists := target.Labels[k]; !exists {
390+
target.Labels[k] = v
391+
}
392+
}
393+
}
394+
if len(template.Annotations) > 0 {
395+
if target.Annotations == nil {
396+
target.Annotations = make(map[string]string, len(template.Annotations))
397+
}
398+
for k, v := range template.Annotations {
399+
if _, exists := target.Annotations[k]; !exists {
400+
target.Annotations[k] = v
401+
}
402+
}
403+
}
404+
}
405+
382406
// adoptSandboxFromCandidates picks the best candidate and transfers ownership to the claim.
383-
func (r *SandboxClaimReconciler) adoptSandboxFromCandidates(ctx context.Context, claim *extensionsv1alpha1.SandboxClaim, candidates []*v1alpha1.Sandbox) (*v1alpha1.Sandbox, error) {
407+
func (r *SandboxClaimReconciler) adoptSandboxFromCandidates(ctx context.Context, claim *extensionsv1alpha1.SandboxClaim, template *extensionsv1alpha1.SandboxTemplate, candidates []*v1alpha1.Sandbox) (*v1alpha1.Sandbox, error) {
384408
log := log.FromContext(ctx)
385409

386410
// Sort: ready sandboxes first, then by creation time (oldest first)
@@ -441,6 +465,10 @@ func (r *SandboxClaimReconciler) adoptSandboxFromCandidates(ctx context.Context,
441465
adopted.Annotations[asmetrics.TraceContextAnnotation] = tc
442466
}
443467

468+
if template != nil {
469+
mergeTemplatePodMetadata(&adopted.Spec.PodTemplate.ObjectMeta, template.Spec.PodTemplate.ObjectMeta)
470+
}
471+
444472
// Add sandbox ID label to pod template for NetworkPolicy targeting
445473
if adopted.Spec.PodTemplate.ObjectMeta.Labels == nil {
446474
adopted.Spec.PodTemplate.ObjectMeta.Labels = make(map[string]string)
@@ -647,7 +675,12 @@ func (r *SandboxClaimReconciler) getOrCreateSandbox(ctx context.Context, claim *
647675

648676
// Try to adopt from warm pool
649677
if len(adoptionCandidates) > 0 {
650-
adopted, err := r.adoptSandboxFromCandidates(ctx, claim, adoptionCandidates)
678+
var template *extensionsv1alpha1.SandboxTemplate
679+
template, err := r.getTemplate(ctx, claim)
680+
if err != nil && !k8errors.IsNotFound(err) {
681+
return nil, err
682+
}
683+
adopted, err := r.adoptSandboxFromCandidates(ctx, claim, template, adoptionCandidates)
651684
if err != nil {
652685
return nil, err
653686
}

extensions/controllers/sandboxclaim_controller_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,12 @@ func TestSandboxClaimAdoptionAppliesWorkspaceResources(t *testing.T) {
12771277
ObjectMeta: metav1.ObjectMeta{Name: "test-template", Namespace: "default"},
12781278
Spec: extensionsv1alpha1.SandboxTemplateSpec{
12791279
PodTemplate: sandboxv1alpha1.PodTemplate{
1280+
ObjectMeta: sandboxv1alpha1.PodMetadata{
1281+
Annotations: map[string]string{
1282+
"io.codewire.sh/workspace": "true",
1283+
"test-annotation": "template",
1284+
},
1285+
},
12801286
Spec: corev1.PodSpec{
12811287
Containers: []corev1.Container{
12821288
{Name: "workspace", Image: "workspace:latest"},
@@ -1320,6 +1326,11 @@ func TestSandboxClaimAdoptionAppliesWorkspaceResources(t *testing.T) {
13201326
Spec: sandboxv1alpha1.SandboxSpec{
13211327
Replicas: ptr.To(int32(1)),
13221328
PodTemplate: sandboxv1alpha1.PodTemplate{
1329+
ObjectMeta: sandboxv1alpha1.PodMetadata{
1330+
Annotations: map[string]string{
1331+
"io.codewire.sh/workspace": "true",
1332+
},
1333+
},
13231334
Spec: corev1.PodSpec{
13241335
Containers: []corev1.Container{
13251336
{Name: "workspace", Image: "workspace:latest"},
@@ -1389,6 +1400,12 @@ func TestSandboxClaimAdoptionAppliesWorkspaceResources(t *testing.T) {
13891400
if len(sidecar.Resources.Requests) != 0 || len(sidecar.Resources.Limits) != 0 {
13901401
t.Fatalf("expected adopted sidecar resources to remain untouched, got requests=%v limits=%v", sidecar.Resources.Requests, sidecar.Resources.Limits)
13911402
}
1403+
if got := adopted.Spec.PodTemplate.ObjectMeta.Annotations["io.codewire.sh/workspace"]; got != "true" {
1404+
t.Fatalf("expected adopted workspace annotation to survive, got %q", got)
1405+
}
1406+
if got := adopted.Spec.PodTemplate.ObjectMeta.Annotations["test-annotation"]; got != "template" {
1407+
t.Fatalf("expected template annotation to be restored on adoption, got %q", got)
1408+
}
13921409
}
13931410

13941411
func TestRecordCreationLatencyMetric(t *testing.T) {

0 commit comments

Comments
 (0)