From dc7ff443037be339451e798e9374e7a93aca3194 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 5 Sep 2019 09:49:41 -0700 Subject: [PATCH] Add unit tests for #584 --- README.md | 2 +- node/pod_test.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ node/queue.go | 2 +- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e4f741e79..c1dd7262f 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ type PodLifecycleHandler interface { ``` There is also an optional interface `PodNotifier` which enables the provider to -asyncronously notify the virtual-kubelet about pod status changes. If this +asynchronously notify the virtual-kubelet about pod status changes. If this interface is not implemented, virtual-kubelet will periodically check the status of all pods. diff --git a/node/pod_test.go b/node/pod_test.go index 7fecc0826..4f8f4f752 100644 --- a/node/pod_test.go +++ b/node/pod_test.go @@ -17,6 +17,7 @@ package node import ( "context" "testing" + "time" pkgerrors "github.com/pkg/errors" "github.com/virtual-kubelet/virtual-kubelet/errdefs" @@ -212,6 +213,77 @@ func TestPodDelete(t *testing.T) { } } +func TestPodUpdateStatus(t *testing.T) { + startedAt := metav1.NewTime(time.Now()) + finishedAt := metav1.NewTime(startedAt.Add(time.Second * 10)) + containerStateRunning := &corev1.ContainerStateRunning{StartedAt: startedAt} + containerStateTerminated := &corev1.ContainerStateTerminated{StartedAt: startedAt, FinishedAt: finishedAt} + containerStateWaiting := &corev1.ContainerStateWaiting{} + + testCases := []struct { + desc string + running *corev1.ContainerStateRunning + terminated *corev1.ContainerStateTerminated + waiting *corev1.ContainerStateWaiting + expectedStartedAt metav1.Time + expectedFinishedAt metav1.Time + }{ + {desc: "container in running state", running: containerStateRunning, expectedStartedAt: startedAt}, + {desc: "container in terminated state", terminated: containerStateTerminated, expectedStartedAt: startedAt, expectedFinishedAt: finishedAt}, + {desc: "container in waiting state", waiting: containerStateWaiting}, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + c := newTestController() + pod := &corev1.Pod{} + pod.ObjectMeta.Namespace = "default" + pod.ObjectMeta.Name = "nginx" + pod.Status.Phase = corev1.PodRunning + containerStatus := corev1.ContainerStatus{} + if tc.running != nil { + containerStatus.State.Running = tc.running + } else if tc.terminated != nil { + containerStatus.State.Terminated = tc.terminated + } else if tc.waiting != nil { + containerStatus.State.Waiting = tc.waiting + } + pod.Status.ContainerStatuses = []corev1.ContainerStatus{containerStatus} + + pc := c.client.CoreV1().Pods("default") + p, err := pc.Create(pod) + assert.NilError(t, err) + + ctx := context.Background() + err = c.updatePodStatus(ctx, p.DeepCopy()) + assert.NilError(t, err) + + updatedPod, err := pc.Get(pod.Name, metav1.GetOptions{}) + assert.Equal(t, updatedPod.Status.Phase, corev1.PodFailed) + assert.Assert(t, is.Len(updatedPod.Status.ContainerStatuses, 1)) + assert.Assert(t, updatedPod.Status.ContainerStatuses[0].State.Running == nil) + + // Test cases for running and terminated container state + if tc.running != nil || tc.terminated != nil { + // Ensure that the container is in terminated state and other states are nil + assert.Assert(t, updatedPod.Status.ContainerStatuses[0].State.Terminated != nil) + assert.Assert(t, updatedPod.Status.ContainerStatuses[0].State.Waiting == nil) + + terminated := updatedPod.Status.ContainerStatuses[0].State.Terminated + assert.Equal(t, terminated.StartedAt, tc.expectedStartedAt) + assert.Assert(t, terminated.StartedAt.Before(&terminated.FinishedAt)) + if tc.terminated != nil { + assert.Equal(t, terminated.FinishedAt, tc.expectedFinishedAt) + } + } else { + // Test case for waiting container state + assert.Assert(t, updatedPod.Status.ContainerStatuses[0].State.Terminated == nil) + assert.Assert(t, updatedPod.Status.ContainerStatuses[0].State.Waiting != nil) + } + }) + } +} + func newPodSpec() corev1.PodSpec { return corev1.PodSpec{ Containers: []corev1.Container{ diff --git a/node/queue.go b/node/queue.go index d9355d098..891ef2edd 100644 --- a/node/queue.go +++ b/node/queue.go @@ -116,7 +116,7 @@ func (pc *PodController) processPodStatusUpdate(ctx context.Context, workerID st return handleQueueItem(ctx, q, pc.podStatusHandler) } -// providerSyncLoop syncronizes pod states from the provider back to kubernetes +// providerSyncLoop synchronizes pod states from the provider back to kubernetes // Deprecated: This is only used when the provider does not support async updates // Providers should implement async update support, even if it just means copying // something like this in.