Skip to content

Add unit tests for pod APIs under pkg/datastore #712

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Apr 25, 2025
Merged
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
256acf8
Add unit test coverage for pod APIs under datastore/pkg
rlakhtakia Apr 18, 2025
7b0d548
Merge branch 'kubernetes-sigs:main' into main
rlakhtakia Apr 18, 2025
0b7f537
Add unit test coverage for pod APIs under datastore/pkg
rlakhtakia Apr 18, 2025
2ba431d
Add unit test coverage for pod APIs under datastore/pkg
rlakhtakia Apr 18, 2025
5067fac
Add unit test coverage for pod APIs under datastore/pkg
rlakhtakia Apr 18, 2025
9b71677
EPP Architecture proposal (#683)
kfswain Apr 21, 2025
bfbc35f
removed unused Fake struct (#723)
nirrozenbaum Apr 22, 2025
fc980b8
epp: return correct response for trailers (#726)
howardjohn Apr 22, 2025
55600b4
Refactor scheduler to run plugins (#677)
liu-cong Apr 22, 2025
bf64a93
Complete the InferencePool documentation (#673)
nicolexin Apr 23, 2025
76a562f
reduce log level in metrics logger not to trash the log (#708)
nirrozenbaum Apr 23, 2025
7792676
few updates in datastore (#713)
nirrozenbaum Apr 23, 2025
d167e49
scheduler refactoring (#730)
nirrozenbaum Apr 23, 2025
c262a1d
filter irrelevant pod in pod_reconciler (#696)
nayihz Apr 23, 2025
4707ab2
EPP: Update GetRandomPod() to return nil if no pods exist (#731)
danehans Apr 23, 2025
ec4af3b
Move filter and scorer plugins registration to a separate file (#729)
mayabar Apr 24, 2025
e03802a
Update issue templates (#738)
kfswain Apr 24, 2025
f93cbe6
Add unit test coverage for pod APIs under datastore/pkg
rlakhtakia Apr 18, 2025
56eb52f
few updates in datastore (#713)
nirrozenbaum Apr 23, 2025
56d20e5
few updates in datastore (#713)
nirrozenbaum Apr 23, 2025
124369e
Add unit test coverage for pod APIs under datastore/pkg
rlakhtakia Apr 18, 2025
44f424a
Merge branch 'main' of https://github.com/rlakhtakia/gateway-api-infe…
rlakhtakia Apr 25, 2025
df39f48
Merge branch 'main' of https://github.com/kubernetes-sigs/gateway-api…
rlakhtakia Apr 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions pkg/epp/datastore/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import (
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/gateway-api-inference-extension/api/v1alpha2"
backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
testutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/testing"
Expand Down Expand Up @@ -340,3 +343,121 @@ func TestMetrics(t *testing.T) {
})
}
}

func TestPods(t *testing.T) {
poolSelector := map[string]string{"app": "vllm_v1"}
pool := testutil.MakeInferencePool("pool").
Namespace("default").
Selector(poolSelector).ObjRef()
updatedPod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
},
Spec: corev1.PodSpec{
NodeName: "node-1",
},
}
notReadyPod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Status: corev1.PodStatus{
Conditions: []corev1.PodCondition{{Type: corev1.PodReady, Status: corev1.ConditionFalse}},
},
}
tests := []struct {
name string
op func(ctx context.Context, ds Datastore)
existingPods []*corev1.Pod
wantPods []*corev1.Pod
}{
{
name: "Add new pod, no existing pods, should add",
existingPods: []*corev1.Pod{},
wantPods: []*corev1.Pod{pod1},
op: func(ctx context.Context, ds Datastore) {
ds.PodUpdateOrAddIfNotExist(pod1, pool)
},
},
{
name: "Add new pod, with existing pods, should add",
existingPods: []*corev1.Pod{pod1},
wantPods: []*corev1.Pod{pod1, pod2},
op: func(ctx context.Context, ds Datastore) {
ds.PodUpdateOrAddIfNotExist(pod2, pool)
},
},
{
name: "Update existing pod, new field, should update",
existingPods: []*corev1.Pod{pod1},
wantPods: []*corev1.Pod{updatedPod},
op: func(ctx context.Context, ds Datastore) {
ds.PodUpdateOrAddIfNotExist(updatedPod, pool)
},
},
{
name: "Update existing pod, no new fields, should not update",
existingPods: []*corev1.Pod{pod1},
wantPods: []*corev1.Pod{pod1},
op: func(ctx context.Context, ds Datastore) {
incoming := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
Namespace: "default",
},
}
ds.PodUpdateOrAddIfNotExist(incoming, pool)
},
},
{
name: "Add not ready pod, resync required, should update",
existingPods: []*corev1.Pod{pod1, notReadyPod},
wantPods: []*corev1.Pod{pod1, pod2},
op: func(ctx context.Context, ds Datastore) {
scheme := runtime.NewScheme()
cfg := config.GetConfigOrDie()
cli, err := client.New(cfg, client.Options{Scheme: scheme})
if err != nil {
t.Fatalf("Unable to create ctrl runtime client")
}
ds.PodResyncAll(ctx, cli, pool)
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pod resync is not required on pod not ready. it is required when inf pool label selector is changed.
generally, I've been working on datastore a bit (started refactoring, pushed a small PR and more to come),
IMO PodResyncAll should be removed from the interface.
having said that, the internal behavior is still there and is called upon a change in the pool label selector.
more details in the PR #713

},
{
name: "Delete the pod",
existingPods: []*corev1.Pod{pod1, pod2},
wantPods: []*corev1.Pod{pod1},
op: func(ctx context.Context, ds Datastore) {
ds.PodDelete(pod2NamespacedName)
},
},
{
name: "Delete the pod that doesn't exist",
existingPods: []*corev1.Pod{pod1},
wantPods: []*corev1.Pod{pod1},
op: func(ctx context.Context, ds Datastore) {
ds.PodDelete(pod2NamespacedName)
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := context.Background()
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
ds := NewDatastore(t.Context(), pmf)
for _, pod := range test.existingPods {
ds.PodUpdateOrAddIfNotExist(pod, pool)
}

test.op(ctx, ds)
var gotPods []*corev1.Pod
for _, pm := range ds.PodGetAll() {
pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: pm.GetPod().NamespacedName.Name, Namespace: pm.GetPod().NamespacedName.Namespace}, Status: corev1.PodStatus{PodIP: pm.GetPod().Address}}
gotPods = append(gotPods, pod)
}
if !cmp.Equal(gotPods, test.wantPods, cmpopts.SortSlices(func(a, b *corev1.Pod) bool { return a.Name < b.Name })) {
t.Logf("got (%v) != want (%v);", gotPods, test.wantPods)
}
})
}
}