diff --git a/runtime/kubernetes/container_test.go b/runtime/kubernetes/container_test.go index 0d3e7d3a..4b5e14d2 100644 --- a/runtime/kubernetes/container_test.go +++ b/runtime/kubernetes/container_test.go @@ -12,6 +12,7 @@ import ( "github.com/go-vela/types/pipeline" velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" ) @@ -433,3 +434,123 @@ func TestKubernetes_WaitContainer(t *testing.T) { }) } } + +func Test_podTracker_inspectContainerStatuses(t *testing.T) { + // setup types + logger := logrus.NewEntry(logrus.StandardLogger()) + + tests := []struct { + name string + trackedPod string + ctnName string + terminated bool + pod *v1.Pod + }{ + { + name: "container is terminated", + trackedPod: "test/github-octocat-1", + ctnName: "step-github-octocat-1-clone", + terminated: true, + pod: _pod, + }, + { + name: "pod is pending", + trackedPod: "test/github-octocat-1", + ctnName: "step-github-octocat-1-clone", + terminated: false, + pod: &v1.Pod{ + ObjectMeta: _pod.ObjectMeta, + TypeMeta: _pod.TypeMeta, + Spec: _pod.Spec, + Status: v1.PodStatus{ + Phase: v1.PodPending, + }, + }, + }, + { + name: "container is running", + trackedPod: "test/github-octocat-1", + ctnName: "step-github-octocat-1-clone", + terminated: false, + pod: &v1.Pod{ + ObjectMeta: _pod.ObjectMeta, + TypeMeta: _pod.TypeMeta, + Spec: _pod.Spec, + Status: v1.PodStatus{ + Phase: v1.PodRunning, + ContainerStatuses: []v1.ContainerStatus{ + { + Name: "step-github-octocat-1-clone", + State: v1.ContainerState{ + Running: &v1.ContainerStateRunning{}, + }, + }, + }, + }, + }, + }, + { + name: "pod has an untracked container", + trackedPod: "test/github-octocat-1", + ctnName: "step-github-octocat-1-clone", + terminated: true, + pod: &v1.Pod{ + ObjectMeta: _pod.ObjectMeta, + TypeMeta: _pod.TypeMeta, + Spec: _pod.Spec, + Status: v1.PodStatus{ + Phase: v1.PodRunning, + ContainerStatuses: []v1.ContainerStatus{ + { + Name: "step-github-octocat-1-clone", + State: v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + Reason: "Completed", + ExitCode: 0, + }, + }, + }, + { + Name: "injected-by-admissions-controller", + State: v1.ContainerState{ + Running: &v1.ContainerStateRunning{}, + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctnTracker := containerTracker{ + Name: tt.ctnName, + Terminated: make(chan struct{}), + } + podTracker := podTracker{ + Logger: logger, + TrackedPod: tt.trackedPod, + Containers: map[string]*containerTracker{}, + // other fields not used by inspectContainerStatuses + // if they're needed, use newPodTracker + } + podTracker.Containers[tt.ctnName] = &ctnTracker + + podTracker.inspectContainerStatuses(tt.pod) + + func() { + defer func() { + // nolint: errcheck // repeat close() panics (otherwise it won't) + recover() + }() + + close(ctnTracker.Terminated) + + // this will only run if close() did not panic + if tt.terminated { + t.Error("inspectContainerStatuses should have signaled termination") + } + }() + }) + } +}