From 1b876bd130da75f8eeaffd6cdd561d266a28d70a Mon Sep 17 00:00:00 2001
From: kaihsun <kaihsun@anyscale.com>
Date: Mon, 24 Apr 2023 17:27:31 +0000
Subject: [PATCH] init container resource

---
 ray-operator/controllers/ray/common/pod.go      | 8 ++++++--
 ray-operator/controllers/ray/common/pod_test.go | 6 ++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/ray-operator/controllers/ray/common/pod.go b/ray-operator/controllers/ray/common/pod.go
index e31c7fae62e..9d1310bdd3c 100644
--- a/ray-operator/controllers/ray/common/pod.go
+++ b/ray-operator/controllers/ray/common/pod.go
@@ -191,6 +191,8 @@ func DefaultWorkerPodTemplate(instance rayiov1alpha1.RayCluster, workerSpec rayi
 
 	// The Ray worker should only start once the GCS server is ready.
 	rayContainerIndex := getRayContainerIndex(podTemplate.Spec)
+	// Do not modify `deepCopyRayContainer` anywhere.
+	deepCopyRayContainer := podTemplate.Spec.Containers[rayContainerIndex].DeepCopy()
 	initContainer := v1.Container{
 		Name:            "wait-gcs-ready",
 		Image:           podTemplate.Spec.Containers[rayContainerIndex].Image,
@@ -203,8 +205,10 @@ func DefaultWorkerPodTemplate(instance rayiov1alpha1.RayCluster, workerSpec rayi
 		// This init container requires certain environment variables to establish a secure connection with the Ray head using TLS authentication.
 		// Additionally, some of these environment variables may reference files stored in volumes, so we need to include both the `Env` and `VolumeMounts` fields here.
 		// For more details, please refer to: https://docs.ray.io/en/latest/ray-core/configure.html#tls-authentication.
-		Env:          podTemplate.Spec.Containers[rayContainerIndex].DeepCopy().Env,
-		VolumeMounts: podTemplate.Spec.Containers[rayContainerIndex].DeepCopy().VolumeMounts,
+		Env:          deepCopyRayContainer.Env,
+		VolumeMounts: deepCopyRayContainer.VolumeMounts,
+		// If users specify ResourceQuota for the namespace, the init container need to specify resource explicitly.
+		Resources: deepCopyRayContainer.Resources,
 	}
 	podTemplate.Spec.InitContainers = append(podTemplate.Spec.InitContainers, initContainer)
 
diff --git a/ray-operator/controllers/ray/common/pod_test.go b/ray-operator/controllers/ray/common/pod_test.go
index 944d5a7c5eb..a12dc5365bd 100644
--- a/ray-operator/controllers/ray/common/pod_test.go
+++ b/ray-operator/controllers/ray/common/pod_test.go
@@ -827,6 +827,8 @@ func TestDefaultInitContainer(t *testing.T) {
 	// Ray container to the init container. This may be changed in the future.
 	healthCheckContainer := podTemplateSpec.Spec.InitContainers[numInitContainers-1]
 	rayContainer := worker.Template.Spec.Containers[getRayContainerIndex(worker.Template.Spec)]
+
+	assert.NotEqual(t, len(rayContainer.Env), 0, "The test only makes sense if the Ray container has environment variables.")
 	assert.Equal(t, len(rayContainer.Env), len(healthCheckContainer.Env))
 	for _, env := range rayContainer.Env {
 		// env.ValueFrom is the source for the environment variable's value. Cannot be used if value is not empty.
@@ -836,4 +838,8 @@ func TestDefaultInitContainer(t *testing.T) {
 			checkContainerEnv(t, healthCheckContainer, env.Name, env.ValueFrom.FieldRef.FieldPath)
 		}
 	}
+
+	// The values of `Resources` should be the same in both Ray container and health-check container.
+	assert.NotEmpty(t, rayContainer.Resources, "The test only makes sense if the Ray container has resource limit/request.")
+	assert.Equal(t, rayContainer.Resources, healthCheckContainer.Resources)
 }