e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
168 lines
4.6 KiB
Go
168 lines
4.6 KiB
Go
// Copyright 2025 Alibaba Group Holding Ltd.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package eviction
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
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/fake"
|
|
|
|
sandboxv1alpha1 "github.com/alibaba/OpenSandbox/sandbox-k8s/apis/sandbox/v1alpha1"
|
|
)
|
|
|
|
func newTestPod(name string, labels map[string]string, deleting bool) *corev1.Pod {
|
|
pod := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: name,
|
|
Namespace: "default",
|
|
Labels: labels,
|
|
},
|
|
}
|
|
if deleting {
|
|
now := metav1.NewTime(time.Now())
|
|
pod.DeletionTimestamp = &now
|
|
pod.Finalizers = []string{"test-finalizer"}
|
|
}
|
|
return pod
|
|
}
|
|
|
|
func TestDefaultEvictionHandler_NeedsEviction(t *testing.T) {
|
|
handler := newDefaultEvictionHandler(nil)
|
|
|
|
tests := []struct {
|
|
name string
|
|
pod *corev1.Pod
|
|
expect bool
|
|
}{
|
|
{
|
|
name: "pod with eviction label",
|
|
pod: newTestPod("pod-1", map[string]string{LabelEvict: ""}, false),
|
|
expect: true,
|
|
},
|
|
{
|
|
name: "pod without eviction label",
|
|
pod: newTestPod("pod-2", map[string]string{"other": "label"}, false),
|
|
expect: false,
|
|
},
|
|
{
|
|
name: "pod with no labels",
|
|
pod: newTestPod("pod-3", nil, false),
|
|
expect: false,
|
|
},
|
|
{
|
|
name: "pod with eviction label but already deleting",
|
|
pod: newTestPod("pod-4", map[string]string{LabelEvict: ""}, true),
|
|
expect: false,
|
|
},
|
|
{
|
|
name: "pod deleting without eviction label",
|
|
pod: newTestPod("pod-5", nil, true),
|
|
expect: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := handler.NeedsEviction(tt.pod)
|
|
if got != tt.expect {
|
|
t.Errorf("NeedsEviction() = %v, want %v", got, tt.expect)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDefaultEvictionHandler_Evict(t *testing.T) {
|
|
scheme := runtime.NewScheme()
|
|
_ = corev1.AddToScheme(scheme)
|
|
|
|
t.Run("deletes a pod", func(t *testing.T) {
|
|
pod := newTestPod("pod-1", map[string]string{LabelEvict: ""}, false)
|
|
c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(pod).Build()
|
|
handler := newDefaultEvictionHandler(c)
|
|
|
|
err := handler.Evict(context.Background(), pod)
|
|
if err != nil {
|
|
t.Fatalf("Evict() returned error: %v", err)
|
|
}
|
|
|
|
got := &corev1.Pod{}
|
|
err = c.Get(context.Background(), keyFor(pod), got)
|
|
if err == nil {
|
|
t.Error("expected pod to be deleted, but it still exists")
|
|
}
|
|
})
|
|
|
|
t.Run("skips pod already deleting", func(t *testing.T) {
|
|
pod := newTestPod("pod-2", map[string]string{LabelEvict: ""}, true)
|
|
c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(pod).Build()
|
|
handler := newDefaultEvictionHandler(c)
|
|
|
|
err := handler.Evict(context.Background(), pod)
|
|
if err != nil {
|
|
t.Fatalf("Evict() returned error: %v", err)
|
|
}
|
|
|
|
got := &corev1.Pod{}
|
|
err = c.Get(context.Background(), keyFor(pod), got)
|
|
if err != nil {
|
|
t.Error("expected pod to still exist since it was already deleting")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestNewEvictionHandler(t *testing.T) {
|
|
scheme := runtime.NewScheme()
|
|
_ = corev1.AddToScheme(scheme)
|
|
_ = sandboxv1alpha1.AddToScheme(scheme)
|
|
c := fake.NewClientBuilder().WithScheme(scheme).Build()
|
|
ctx := context.Background()
|
|
|
|
t.Run("returns default handler when no label", func(t *testing.T) {
|
|
pool := &sandboxv1alpha1.Pool{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "pool-1"},
|
|
}
|
|
h := NewEvictionHandler(ctx, c, pool)
|
|
if h == nil {
|
|
t.Fatal("expected non-nil handler")
|
|
}
|
|
if _, ok := h.(*defaultEvictionHandler); !ok {
|
|
t.Errorf("expected *defaultEvictionHandler, got %T", h)
|
|
}
|
|
})
|
|
|
|
t.Run("returns default handler for unknown label value", func(t *testing.T) {
|
|
pool := &sandboxv1alpha1.Pool{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pool-2",
|
|
Labels: map[string]string{LabelEvictionHandler: "unknown-handler"},
|
|
},
|
|
}
|
|
h := NewEvictionHandler(ctx, c, pool)
|
|
if _, ok := h.(*defaultEvictionHandler); !ok {
|
|
t.Errorf("expected *defaultEvictionHandler, got %T", h)
|
|
}
|
|
})
|
|
}
|
|
|
|
func keyFor(obj metav1.Object) types.NamespacedName {
|
|
return types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}
|
|
}
|