Files
2026-07-13 13:17:40 +08:00

183 lines
6.1 KiB
Python

import json
import sys
import time
import pytest
from ray.cluster_utils import Cluster
from ray.dashboard.consts import RAY_STREAM_RUNTIME_ENV_LOG_TO_JOB_DRIVER_LOG_ENV_VAR
from ray.dashboard.modules.job.tests.conftest import _driver_script_path
from ray.dashboard.modules.job.tests.subprocess_driver_scripts.driver_runtime_env_inheritance import ( # noqa: E501
RUNTIME_ENV_LOG_LINE_PREFIX,
)
from ray.job_submission import JobStatus, JobSubmissionClient
def wait_until_status(client, job_id, status_to_wait_for, timeout_seconds=20):
start = time.time()
while time.time() - start <= timeout_seconds:
status = client.get_job_status(job_id)
print(f"status: {status}")
if status in status_to_wait_for:
return
time.sleep(1)
raise Exception
def wait(client, job_id):
wait_until_status(
client,
job_id,
{JobStatus.SUCCEEDED, JobStatus.STOPPED, JobStatus.FAILED},
timeout_seconds=60,
)
def get_runtime_env_from_logs(client, job_id):
wait(client, job_id)
logs = client.get_job_logs(job_id)
print(logs)
assert client.get_job_status(job_id) == JobStatus.SUCCEEDED
# Split logs by line, find the unique line that starts with
# RUNTIME_ENV_LOG_LINE_PREFIX, strip it and parse it as JSON.
lines = logs.strip().split("\n")
assert len(lines) > 0
for line in lines:
if line.startswith(RUNTIME_ENV_LOG_LINE_PREFIX):
return json.loads(line[len(RUNTIME_ENV_LOG_LINE_PREFIX) :])
def test_job_driver_inheritance():
try:
c = Cluster()
c.add_node(num_cpus=1)
# If using a remote cluster, replace 127.0.0.1 with the head node's IP address.
client = JobSubmissionClient("http://127.0.0.1:8265")
driver_script_path = _driver_script_path("driver_runtime_env_inheritance.py")
job_id = client.submit_job(
entrypoint=f"python {driver_script_path}",
runtime_env={
"env_vars": {"A": "1", "B": "2"},
"pip": ["requests"],
},
)
# Test key is merged
print("Test key merged")
runtime_env = get_runtime_env_from_logs(client, job_id)
assert runtime_env["env_vars"] == {"A": "1", "B": "2", "C": "1"}
assert runtime_env["pip"] == {"packages": ["requests"], "pip_check": False}
# Test worker process setuphook works.
print("Test key setup hook")
expected_str = "HELLOWORLD"
job_id = client.submit_job(
entrypoint=(
f"python {driver_script_path} "
f"--worker-process-setup-hook {expected_str}"
),
runtime_env={
"env_vars": {"A": "1", "B": "2"},
},
)
wait(client, job_id)
logs = client.get_job_logs(job_id)
assert expected_str in logs
# Test raise an exception upon key conflict
print("Test conflicting pip")
job_id = client.submit_job(
entrypoint=f"python {driver_script_path} --conflict=pip",
runtime_env={"pip": ["numpy"]},
)
wait(client, job_id)
status = client.get_job_status(job_id)
logs = client.get_job_logs(job_id)
assert status == JobStatus.FAILED
assert "Failed to merge the Job's runtime env" in logs
# Test raise an exception upon env var conflict
print("Test conflicting env vars")
job_id = client.submit_job(
entrypoint=f"python {driver_script_path} --conflict=env_vars",
runtime_env={
"env_vars": {"A": "1"},
},
)
wait(client, job_id)
status = client.get_job_status(job_id)
logs = client.get_job_logs(job_id)
assert status == JobStatus.FAILED
assert "Failed to merge the Job's runtime env" in logs
finally:
c.shutdown()
@pytest.mark.parametrize("stream_runtime_env_log", ["1", "0"])
def test_runtime_env_logs_streamed_to_job_driver_log(
monkeypatch, stream_runtime_env_log
):
monkeypatch.setenv(
RAY_STREAM_RUNTIME_ENV_LOG_TO_JOB_DRIVER_LOG_ENV_VAR, stream_runtime_env_log
)
try:
c = Cluster()
c.add_node(num_cpus=1)
client = JobSubmissionClient("http://127.0.0.1:8265")
job_id = client.submit_job(
entrypoint="echo hello world",
runtime_env={"pip": ["requests==2.25.1"]},
)
wait(client, job_id)
logs = client.get_job_logs(job_id)
if stream_runtime_env_log == "0":
assert "Creating virtualenv at" not in logs
else:
assert "Creating virtualenv at" in logs
finally:
c.shutdown()
def test_job_driver_inheritance_override(monkeypatch):
monkeypatch.setenv("RAY_OVERRIDE_JOB_RUNTIME_ENV", "1")
try:
c = Cluster()
c.add_node(num_cpus=1)
# If using a remote cluster, replace 127.0.0.1 with the head node's IP address.
client = JobSubmissionClient("http://127.0.0.1:8265")
driver_script_path = _driver_script_path("driver_runtime_env_inheritance.py")
job_id = client.submit_job(
entrypoint=f"python {driver_script_path}",
runtime_env={
"env_vars": {"A": "1", "B": "2"},
"pip": ["requests"],
},
)
# Test conflict resolution regular field
job_id = client.submit_job(
entrypoint=f"python {driver_script_path} --conflict=pip",
runtime_env={"pip": ["pip-install-test==0.5"]},
)
runtime_env = get_runtime_env_from_logs(client, job_id)
print(runtime_env)
assert runtime_env["pip"] == {"packages": ["numpy"], "pip_check": False}
# Test raise an exception upon env var conflict
job_id = client.submit_job(
entrypoint=f"python {driver_script_path} --conflict=env_vars",
runtime_env={
"env_vars": {"A": "2"},
},
)
runtime_env = get_runtime_env_from_logs(client, job_id)
print(runtime_env)
assert runtime_env["env_vars"]["A"] == "1"
finally:
c.shutdown()
if __name__ == "__main__":
sys.exit(pytest.main(["-v", __file__]))