Skip to content

Commit

Permalink
test: added unit test for cleanupDanglingPods (#516)
Browse files Browse the repository at this point in the history
  • Loading branch information
smritidahal653 authored Apr 6, 2023
1 parent 81010aa commit 6a71dd9
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 51 deletions.
105 changes: 105 additions & 0 deletions pkg/provider/podsTracker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"context"
"fmt"
"strings"
"testing"
"time"
Expand All @@ -14,6 +15,7 @@ import (
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
)

func TestUpdatePodStatus(t *testing.T) {
Expand Down Expand Up @@ -158,3 +160,106 @@ func TestProcessPodUpdates(t *testing.T) {
})
}
}

func TestCleanupDanglingPods(t *testing.T) {
podName1 := "pod-" + uuid.New().String()
podName2 := "pod-" + uuid.New().String()
danglingPodName := "pod-" + uuid.New().String()
podNamespace := "ns-" + uuid.New().String()

podsNames := []string{podName1, podName2}
k8sPods := testsutil.CreatePodsList(podsNames, podNamespace)

activePods := testsutil.CreatePodsList([]string{danglingPodName}, podNamespace)
activePods = append(activePods, k8sPods[0], k8sPods[1])

cg1 := testsutil.CreateContainerGroupObj(podName1, podNamespace, "Succeeded",
testsutil.CreateACIContainersListObj(runningState, "Initializing",
testsutil.CgCreationTime.Add(time.Second*2),
testsutil.CgCreationTime.Add(time.Second*3),
false, false, false), "Succeeded")

cg2 := testsutil.CreateContainerGroupObj(podName2, podNamespace, "Succeeded",
testsutil.CreateACIContainersListObj(runningState, "Initializing",
testsutil.CgCreationTime.Add(time.Second*2),
testsutil.CgCreationTime.Add(time.Second*3),
false, false, false), "Succeeded")

cg3 := testsutil.CreateContainerGroupObj(danglingPodName, podNamespace, "Succeeded",
testsutil.CreateACIContainersListObj(runningState, "Initializing",
testsutil.CgCreationTime.Add(time.Second*2),
testsutil.CgCreationTime.Add(time.Second*3),
false, false, false), "Succeeded")

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

aciMocks := createNewACIMock()

aciMocks.MockGetContainerGroupList = func(ctx context.Context, resourceGroup string) ([]*azaciv2.ContainerGroup, error) {
var result []*azaciv2.ContainerGroup
result = append(result, cg1, cg2, cg3)
return result, nil
}

aciMocks.MockGetContainerGroup = func(ctx context.Context, resourceGroup, containerGroupName string) (*azaciv2.ContainerGroup, error) {
switch containerGroupName {
case podName1:
return cg1, nil
case podName2:
return cg2, nil
case danglingPodName:
return cg3, nil
default:
return nil, nil
}
}

aciMocks.MockDeleteContainerGroup = func(ctx context.Context, resourceGroup, cgName string) error {
updatedActivePods := make([]*v1.Pod, 0)

for i := range activePods {
podCgName := fmt.Sprintf("%s-%s", activePods[i].Namespace, activePods[i].Name)
if podCgName != cgName {
updatedActivePods = append(updatedActivePods, activePods[i])
}
}

activePods = updatedActivePods
return nil
}

activePodsLister := NewMockPodLister(mockCtrl)
k8sPodsLister := NewMockPodLister(mockCtrl)
mockPodsNamespaceLister := NewMockPodNamespaceLister(mockCtrl)

aciProvider, err := createTestProvider(aciMocks, NewMockConfigMapLister(mockCtrl),
NewMockSecretLister(mockCtrl), activePodsLister)
if err != nil {
t.Fatal("failed to create the test provider", err)
}

podsTracker := &PodsTracker{
pods: k8sPodsLister,
updateCb: func(updatedPod *v1.Pod) {
},
handler: aciProvider,
}

k8sPodsLister.EXPECT().List(gomock.Any()).Return(k8sPods, nil).AnyTimes()

activePodsLister.EXPECT().Pods(podNamespace).Return(mockPodsNamespaceLister).AnyTimes()
mockPodsNamespaceLister.EXPECT().Get(danglingPodName).Return(activePods[0], nil)
mockPodsNamespaceLister.EXPECT().Get(podName1).Return(activePods[1], nil)
mockPodsNamespaceLister.EXPECT().Get(podName2).Return(activePods[2], nil)

aciProvider.tracker = podsTracker
podsTracker.cleanupDanglingPods(context.Background())

assert.Equal(t, len(activePods), 2, "The dangling pod should be deleted from activePods")
for i := range activePods {
if !equality.Semantic.DeepEqual(activePods[i], k8sPods[i]) {
t.Errorf("activePods and k8sPods should be in sync. Expected %#v, got %#v", k8sPods[i], activePods[i])
}
}
}
102 changes: 51 additions & 51 deletions pkg/tests/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
azaciv2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2"
"github.com/google/uuid"
"github.com/virtual-kubelet/azure-aci/pkg/util"
v12 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -183,54 +183,54 @@ func CreateCGProbeObj(hasHTTPGet, hasExec bool) *azaciv2.ContainerProbe {
}
}

func GetPodConditions(creationTime, readyConditionTime v1.Time, readyConditionStatus v12.ConditionStatus) []v12.PodCondition {
return []v12.PodCondition{
func GetPodConditions(creationTime, readyConditionTime v1.Time, readyConditionStatus corev1.ConditionStatus) []corev1.PodCondition {
return []corev1.PodCondition{
{
Type: v12.PodReady,
Type: corev1.PodReady,
Status: readyConditionStatus,
LastTransitionTime: readyConditionTime,
}, {
Type: v12.PodInitialized,
Status: v12.ConditionTrue,
Type: corev1.PodInitialized,
Status: corev1.ConditionTrue,
LastTransitionTime: creationTime,
}, {
Type: v12.PodScheduled,
Status: v12.ConditionTrue,
Type: corev1.PodScheduled,
Status: corev1.ConditionTrue,
LastTransitionTime: creationTime,
},
}
}

func CreatePodObj(podName, podNamespace string) *v12.Pod {
return &v12.Pod{
func CreatePodObj(podName, podNamespace string) *corev1.Pod {
return &corev1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: podName,
Namespace: podNamespace,
},
Spec: v12.PodSpec{
Containers: []v12.Container{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "nginx",
Ports: []v12.ContainerPort{
Ports: []corev1.ContainerPort{
{
Name: "http",
ContainerPort: 8080,
},
},
Resources: v12.ResourceRequirements{
Requests: v12.ResourceList{
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
"cpu": resource.MustParse("0.99"),
"memory": resource.MustParse("1.5G"),
},
Limits: v12.ResourceList{
Limits: corev1.ResourceList{
"cpu": resource.MustParse("3999m"),
"memory": resource.MustParse("8010M"),
},
},

LivenessProbe: &v12.Probe{
ProbeHandler: v12.ProbeHandler{
HTTPGet: &v12.HTTPGetAction{
LivenessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Port: intstr.FromString("http"),
Path: "/",
},
Expand All @@ -241,9 +241,9 @@ func CreatePodObj(podName, podNamespace string) *v12.Pod {
SuccessThreshold: 3,
FailureThreshold: 5,
},
ReadinessProbe: &v12.Probe{
ProbeHandler: v12.ProbeHandler{
HTTPGet: &v12.HTTPGetAction{
ReadinessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Port: intstr.FromInt(8080),
Path: "/",
},
Expand All @@ -260,19 +260,19 @@ func CreatePodObj(podName, podNamespace string) *v12.Pod {
}
}

func CreatePodProbeObj(hasHTTPGet, hasExec bool) *v12.Probe {
var httpGet *v12.HTTPGetAction
var exec *v12.ExecAction
func CreatePodProbeObj(hasHTTPGet, hasExec bool) *corev1.Probe {
var httpGet *corev1.HTTPGetAction
var exec *corev1.ExecAction

if hasHTTPGet {
httpGet = &v12.HTTPGetAction{
httpGet = &corev1.HTTPGetAction{
Port: intstr.FromString("http"),
Path: "/",
Scheme: "http",
}
}
if hasExec {
exec = &v12.ExecAction{
exec = &corev1.ExecAction{
Command: []string{
"/bin/sh",
"-c",
Expand All @@ -281,54 +281,54 @@ func CreatePodProbeObj(hasHTTPGet, hasExec bool) *v12.Probe {
}
}

return &v12.Probe{
ProbeHandler: v12.ProbeHandler{
return &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: httpGet,
Exec: exec,
},
}
}

func CreateContainerPortObj(portName string, containerPort int32) []v12.ContainerPort {
return []v12.ContainerPort{
func CreateContainerPortObj(portName string, containerPort int32) []corev1.ContainerPort {
return []corev1.ContainerPort{
{
Name: portName,
ContainerPort: containerPort,
},
}
}

func CreatePodVolumeObj(azureFileVolumeName string, fakeSecretName string, projectedVolumeName string) []v12.Volume {
func CreatePodVolumeObj(azureFileVolumeName string, fakeSecretName string, projectedVolumeName string) []corev1.Volume {
emptyVolumeName := "emptyVolumeName"
fakeShareName1 := "aksshare1"

return []v12.Volume{
return []corev1.Volume{
{
Name: emptyVolumeName,
VolumeSource: v12.VolumeSource{
EmptyDir: &v12.EmptyDirVolumeSource{},
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
{
Name: azureFileVolumeName,
VolumeSource: v12.VolumeSource{
AzureFile: &v12.AzureFileVolumeSource{
VolumeSource: corev1.VolumeSource{
AzureFile: &corev1.AzureFileVolumeSource{
ShareName: fakeShareName1,
SecretName: fakeSecretName,
ReadOnly: true,
},
},
}, {
Name: projectedVolumeName,
VolumeSource: v12.VolumeSource{
Projected: &v12.ProjectedVolumeSource{
Sources: []v12.VolumeProjection{
VolumeSource: corev1.VolumeSource{
Projected: &corev1.ProjectedVolumeSource{
Sources: []corev1.VolumeProjection{
{
ConfigMap: &v12.ConfigMapProjection{
LocalObjectReference: v12.LocalObjectReference{
ConfigMap: &corev1.ConfigMapProjection{
LocalObjectReference: corev1.LocalObjectReference{
Name: "kube-root-ca.crt",
},
Items: []v12.KeyToPath{
Items: []corev1.KeyToPath{
{
Key: "ca.crt",
Path: "ca.crt",
Expand All @@ -343,22 +343,22 @@ func CreatePodVolumeObj(azureFileVolumeName string, fakeSecretName string, proje
}
}

func CreatePodsList(podNames []string, podNameSpace string) []*v12.Pod {
result := make([]*v12.Pod, 0, len(podNames))
func CreatePodsList(podNames []string, podNameSpace string) []*corev1.Pod {
result := make([]*corev1.Pod, 0, len(podNames))
for _, podName := range podNames {
pod := &v12.Pod{
pod := &corev1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: podName,
Namespace: podNameSpace,
CreationTimestamp: v1.NewTime(time.Now()),
UID: types.UID(uuid.New().String()),
},
Status: v12.PodStatus{
Phase: v12.PodRunning,
ContainerStatuses: []v12.ContainerStatus {
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
ContainerStatuses: []corev1.ContainerStatus{
{
State: v12.ContainerState {
Running: &v12.ContainerStateRunning{
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: v1.NewTime(time.Now()),
},
},
Expand Down

0 comments on commit 6a71dd9

Please sign in to comment.