Skip to content

Commit 67cdb6a

Browse files
committed
add testing
1 parent c90a5ef commit 67cdb6a

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

ray-operator/controllers/ray/raycluster_controller_unit_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/ray-project/kuberay/ray-operator/controllers/ray/common"
2626
"github.com/ray-project/kuberay/ray-operator/controllers/ray/utils"
2727
"github.com/ray-project/kuberay/ray-operator/pkg/client/clientset/versioned/scheme"
28+
"github.com/ray-project/kuberay/ray-operator/pkg/features"
2829

2930
. "github.com/onsi/ginkgo/v2"
3031
"github.com/stretchr/testify/assert"
@@ -33,6 +34,7 @@ import (
3334
corev1 "k8s.io/api/core/v1"
3435
rbacv1 "k8s.io/api/rbac/v1"
3536
k8serrors "k8s.io/apimachinery/pkg/api/errors"
37+
"k8s.io/apimachinery/pkg/api/meta"
3638
"k8s.io/apimachinery/pkg/api/resource"
3739
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3840
"k8s.io/apimachinery/pkg/labels"
@@ -1664,6 +1666,13 @@ func TestCalculateStatus(t *testing.T) {
16641666
Status: corev1.PodStatus{
16651667
PodIP: headNodeIP,
16661668
Phase: corev1.PodRunning,
1669+
Conditions: []corev1.PodCondition{
1670+
// The head Pod is ready
1671+
{
1672+
Type: corev1.PodReady,
1673+
Status: corev1.ConditionTrue,
1674+
},
1675+
},
16671676
},
16681677
}
16691678
runtimeObjects := []runtime.Object{headPod, headService}
@@ -1687,6 +1696,47 @@ func TestCalculateStatus(t *testing.T) {
16871696
assert.Equal(t, headService.Name, newInstance.Status.Head.ServiceName)
16881697
assert.NotNil(t, newInstance.Status.StateTransitionTimes, "Cluster state transition timestamp should be created")
16891698
assert.Equal(t, newInstance.Status.LastUpdateTime, newInstance.Status.StateTransitionTimes[rayv1.Ready])
1699+
1700+
// Test CheckRayHeadRunningAndReady with feature gate disabled
1701+
newInstance, _ = r.calculateStatus(ctx, testRayCluster, nil)
1702+
assert.Empty(t, newInstance.Status.Conditions)
1703+
1704+
// enable feature gate for the following tests
1705+
defer features.SetFeatureGateDuringTest(t, features.RayClusterStatusConditions, true)()
1706+
1707+
// Test CheckRayHeadRunningAndReady with head pod running and ready
1708+
newInstance, _ = r.calculateStatus(ctx, testRayCluster, nil)
1709+
assert.True(t, meta.IsStatusConditionPresentAndEqual(newInstance.Status.Conditions, string(rayv1.HeadReady), metav1.ConditionTrue))
1710+
condition := meta.FindStatusCondition(newInstance.Status.Conditions, string(rayv1.HeadReady))
1711+
assert.Equal(t, "HeadPodRunningAndReady", condition.Reason)
1712+
assert.Equal(t, "Head pod is running and ready", condition.Message)
1713+
1714+
// Test CheckRayHeadRunningAndReady with feature gate enabled and head pod not ready
1715+
headPod.Status.Conditions = []corev1.PodCondition{
1716+
{
1717+
Type: corev1.PodReady,
1718+
Status: corev1.ConditionFalse,
1719+
},
1720+
}
1721+
runtimeObjects = []runtime.Object{headPod, headService}
1722+
fakeClient = clientFake.NewClientBuilder().WithScheme(newScheme).WithRuntimeObjects(runtimeObjects...).Build()
1723+
r.Client = fakeClient
1724+
newInstance, _ = r.calculateStatus(ctx, testRayCluster, nil)
1725+
assert.True(t, meta.IsStatusConditionPresentAndEqual(newInstance.Status.Conditions, string(rayv1.HeadReady), metav1.ConditionFalse))
1726+
condition = meta.FindStatusCondition(newInstance.Status.Conditions, string(rayv1.HeadReady))
1727+
assert.Equal(t, "HeadPodNotReady", condition.Reason)
1728+
assert.Equal(t, "Head pod is not ready", condition.Message)
1729+
1730+
// Test CheckRayHeadRunningAndReady with feature gate enabled and head pod not running
1731+
headPod.Status.Phase = corev1.PodFailed
1732+
runtimeObjects = []runtime.Object{headPod, headService}
1733+
fakeClient = clientFake.NewClientBuilder().WithScheme(newScheme).WithRuntimeObjects(runtimeObjects...).Build()
1734+
r.Client = fakeClient
1735+
newInstance, _ = r.calculateStatus(ctx, testRayCluster, nil)
1736+
assert.True(t, meta.IsStatusConditionPresentAndEqual(newInstance.Status.Conditions, string(rayv1.HeadReady), metav1.ConditionFalse))
1737+
condition = meta.FindStatusCondition(newInstance.Status.Conditions, string(rayv1.HeadReady))
1738+
assert.Equal(t, "HeadPodNotRunning", condition.Reason)
1739+
assert.Equal(t, "Head pod is not running", condition.Message)
16901740
}
16911741

16921742
func TestStateTransitionTimes_NoStateChange(t *testing.T) {

ray-operator/controllers/ray/utils/util_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,31 @@ func createSomePodWithCondition(typ corev1.PodConditionType, status corev1.Condi
201201
}
202202
}
203203

204+
func createRayHeadPodWithPhaseAndCOndition(phase corev1.PodPhase, typ corev1.PodConditionType, status corev1.ConditionStatus) (pod *corev1.Pod) {
205+
return &corev1.Pod{
206+
TypeMeta: metav1.TypeMeta{
207+
APIVersion: "v1",
208+
Kind: "Pod",
209+
},
210+
ObjectMeta: metav1.ObjectMeta{
211+
Name: "raycluster-sample-head",
212+
Namespace: "default",
213+
Labels: map[string]string{
214+
"ray.io/node-type": string(rayv1.HeadNode),
215+
},
216+
},
217+
Status: corev1.PodStatus{
218+
Phase: phase,
219+
Conditions: []corev1.PodCondition{
220+
{
221+
Type: typ,
222+
Status: status,
223+
},
224+
},
225+
},
226+
}
227+
}
228+
204229
func TestGetHeadGroupServiceAccountName(t *testing.T) {
205230
tests := map[string]struct {
206231
input *rayv1.RayCluster
@@ -523,3 +548,42 @@ env_vars:
523548
})
524549
}
525550
}
551+
552+
func TestCheckRayHeadRunningAndReady(t *testing.T) {
553+
tests := map[string]struct {
554+
pods corev1.PodList
555+
expected bool
556+
}{
557+
"should return true if Ray head pod is running and ready": {
558+
pods: corev1.PodList{
559+
Items: []corev1.Pod{
560+
*createRayHeadPodWithPhaseAndCOndition(corev1.PodRunning, corev1.PodReady, corev1.ConditionTrue),
561+
},
562+
},
563+
expected: true,
564+
},
565+
"should return false if Ray head pod is not running": {
566+
pods: corev1.PodList{
567+
Items: []corev1.Pod{
568+
*createRayHeadPodWithPhaseAndCOndition(corev1.PodPending, corev1.PodReady, corev1.ConditionFalse),
569+
},
570+
},
571+
expected: false,
572+
},
573+
"should return false if Ray head pod is not ready": {
574+
pods: corev1.PodList{
575+
Items: []corev1.Pod{
576+
*createRayHeadPodWithPhaseAndCOndition(corev1.PodRunning, corev1.PodReady, corev1.ConditionFalse),
577+
},
578+
},
579+
expected: false,
580+
},
581+
}
582+
583+
for name, tc := range tests {
584+
t.Run(name, func(t *testing.T) {
585+
isRunning, _, _ := CheckRayHeadRunningAndReady(context.Background(), tc.pods)
586+
assert.Equal(t, tc.expected, isRunning)
587+
})
588+
}
589+
}

0 commit comments

Comments
 (0)