Skip to content

Commit b6a6d84

Browse files
committed
fix(reflection): terminated pod reflection logic
1 parent f812641 commit b6a6d84

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

pkg/virtualKubelet/reflection/workload/pod.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ func (fpr *FallbackPodReflector) Handle(ctx context.Context, key types.Namespace
305305
return nil
306306
}
307307

308+
// The local pod already failed (terminal), hence no change shall be performed.
309+
if local.Status.Phase == corev1.PodFailed {
310+
return nil
311+
}
312+
308313
// Otherwise, mark the pod as rejected (either Pending or Failed based on its previous status).
309314
phase := corev1.PodPending
310315
reason := forge.PodOffloadingBackOffReason

pkg/virtualKubelet/reflection/workload/pod_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ var _ = Describe("Pod Reflection Tests", func() {
180180
corev1.PodFailed, forge.PodOffloadingAbortedReason),
181181
)
182182
When("phase is running", WhenBody(corev1.PodStatus{Phase: corev1.PodRunning}, corev1.PodFailed, forge.PodOffloadingAbortedReason))
183-
When("phase is failed", WhenBody(corev1.PodStatus{Phase: corev1.PodFailed}, corev1.PodFailed, forge.PodOffloadingAbortedReason))
183+
When("phase is failed", WhenBody(corev1.PodStatus{Phase: corev1.PodFailed}, corev1.PodFailed, ""))
184184
})
185185

186186
When("it is terminating", func() {

pkg/virtualKubelet/reflection/workload/podns.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ func (npr *NamespacedPodReflector) Handle(ctx context.Context, name string) erro
199199
return nil
200200
}
201201

202+
// Skip reflection for pods in a terminal phase (Succeeded or Failed).
203+
// Avoid recreating ShadowPods and changing local pod status when the workload already completed.
204+
if local.Status.Phase == corev1.PodSucceeded || local.Status.Phase == corev1.PodFailed {
205+
klog.V(4).Infof("Skipping reflection of local pod %q as it is in terminal phase %q", npr.LocalRef(name), local.Status.Phase)
206+
return nil
207+
}
208+
202209
// Ensure the local pod has the appropriate labels to mark it as offloaded.
203210
if err := npr.HandleLabels(ctx, local); err != nil {
204211
return err

pkg/virtualKubelet/reflection/workload/podns_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,47 @@ var _ = Describe("Namespaced Pod Reflection Tests", func() {
275275

276276
When("the remote object already exists, but is not managed by the reflection", WhenBodyRemoteNotManagedByReflection())
277277

278+
When("the local object is in terminal phase Succeeded", func() {
279+
BeforeEach(func() {
280+
// Mark local as Succeeded and persist.
281+
local.Status.Phase = corev1.PodSucceeded
282+
UpdatePod(client, &local)
283+
})
284+
285+
It("should succeed", func() { Expect(err).ToNot(HaveOccurred()) })
286+
It("should not create a remote shadowpod", func() {
287+
Expect(GetShadowPodError(liqoClient, RemoteNamespace, PodName)).To(BeNotFound())
288+
})
289+
})
290+
291+
When("the local object is in terminal phase Failed without OffloadingAborted reason and a ShadowPod exists", func() {
292+
BeforeEach(func() {
293+
// Prepare local Failed with a non-aborted reason and ensure it is stored.
294+
local.Status.Phase = corev1.PodFailed
295+
local.Status.Reason = "SomeOtherReason"
296+
UpdatePod(client, &local)
297+
298+
// Create a managed ShadowPod.
299+
shadow.SetLabels(forge.ReflectionLabels())
300+
CreateShadowPod(liqoClient, &shadow)
301+
302+
// Ensure that any attempt to mutate the ShadowPod would fail the test (should not happen).
303+
if c, ok := liqoClient.(*liqoclientfake.Clientset); ok {
304+
c.PrependReactor("update", "shadowpods", func(action testing.Action) (bool, runtime.Object, error) {
305+
return true, nil, fmt.Errorf("should not call update on shadowpods")
306+
})
307+
c.PrependReactor("delete", "shadowpods", func(action testing.Action) (bool, runtime.Object, error) {
308+
return true, nil, fmt.Errorf("should not call delete on shadowpods")
309+
})
310+
}
311+
})
312+
313+
It("should succeed", func() { Expect(err).ToNot(HaveOccurred()) })
314+
It("should not delete the existing remote shadowpod", func() {
315+
Expect(GetShadowPodError(liqoClient, RemoteNamespace, PodName)).ToNot(HaveOccurred())
316+
})
317+
})
318+
278319
When("the local object has already the appropriate offloading label", func() {
279320
BeforeEach(func() {
280321
shouldDenyPodPatches = true

0 commit comments

Comments
 (0)