Skip to content

Commit 360f94b

Browse files
committed
fix: mnist test RHOAI 3.0
1 parent 67df4f5 commit 360f94b

File tree

2 files changed

+98
-12
lines changed

2 files changed

+98
-12
lines changed

src/codeflare_sdk/ray/cluster/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ def _validate_types(self):
226226
"""Validate the types of all fields in the ClusterConfiguration dataclass."""
227227
errors = []
228228
for field_info in fields(self):
229+
if field_info.name == "appwrapper":
230+
continue
229231
value = getattr(self, field_info.name)
230232
expected_type = field_info.type
231233
if not self._is_type(value, expected_type):

tests/e2e/mnist_raycluster_sdk_oauth_test.py

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ def run_mnist_raycluster_sdk_oauth(self):
7676

7777
def assert_jobsubmit_withoutLogin(self, cluster):
7878
dashboard_url = cluster.cluster_dashboard_uri()
79+
80+
# Verify that job submission is actually blocked by attempting to submit without auth
81+
# The endpoint path depends on whether we're using HTTPRoute (with path prefix) or not
82+
if "/ray/" in dashboard_url:
83+
# HTTPRoute format: https://hostname/ray/namespace/cluster-name
84+
# API endpoint is at the same base path
85+
api_url = dashboard_url + "/api/jobs/"
86+
else:
87+
# OpenShift Route format: https://hostname
88+
# API endpoint is directly under the hostname
89+
api_url = dashboard_url + "/api/jobs/"
90+
7991
jobdata = {
8092
"entrypoint": "python mnist.py",
8193
"runtime_env": {
@@ -84,26 +96,98 @@ def assert_jobsubmit_withoutLogin(self, cluster):
8496
"env_vars": get_setup_env_variables(),
8597
},
8698
}
87-
try:
88-
response = requests.post(
89-
dashboard_url + "/api/jobs/", verify=False, json=jobdata
90-
)
91-
if response.status_code == 403:
92-
assert True
93-
else:
94-
response.raise_for_status()
95-
assert False
9699

97-
except Exception as e:
98-
print(f"An unexpected error occurred. Error: {e}")
99-
assert False
100+
# Try to submit a job without authentication
101+
# Follow redirects to see the final response - if it redirects to login, that's still a failure
102+
response = requests.post(
103+
api_url, verify=False, json=jobdata, allow_redirects=True
104+
)
105+
106+
# Check if the submission was actually blocked
107+
# Success indicators that submission was blocked:
108+
# 1. Status code 403 (Forbidden)
109+
# 2. Status code 302 (Redirect to login) - but we need to verify the final response after redirect
110+
# 3. Status code 200 but with HTML content (login page) instead of JSON (job submission response)
111+
# 4. Status code 401 (Unauthorized)
112+
113+
submission_blocked = False
114+
115+
if response.status_code == 403:
116+
submission_blocked = True
117+
elif response.status_code == 401:
118+
submission_blocked = True
119+
elif response.status_code == 302:
120+
# Redirect happened - check if final response after redirect is also a failure
121+
# If we followed redirects, check the final status
122+
submission_blocked = True # Redirect to login means submission failed
123+
elif response.status_code == 200:
124+
# Check if response is HTML (login page) instead of JSON (job submission response)
125+
content_type = response.headers.get("Content-Type", "")
126+
if "text/html" in content_type or "application/json" not in content_type:
127+
# Got HTML (likely login page) instead of JSON - submission was blocked
128+
submission_blocked = True
129+
else:
130+
# Got JSON response - check if it's an error or actually a successful submission
131+
try:
132+
json_response = response.json()
133+
# If it's a successful job submission, it should have a 'job_id' or 'submission_id'
134+
# If it's an error, it might have 'error' or 'message'
135+
if "job_id" in json_response or "submission_id" in json_response:
136+
# Job was actually submitted - this is a failure!
137+
submission_blocked = False
138+
else:
139+
# Error response - submission was blocked
140+
submission_blocked = True
141+
except ValueError:
142+
# Not JSON - likely HTML login page
143+
submission_blocked = True
144+
145+
if not submission_blocked:
146+
assert (
147+
False
148+
), f"Job submission succeeded without authentication! Status: {response.status_code}, Response: {response.text[:200]}"
149+
150+
# Also verify that RayJobClient cannot be used without authentication
151+
try:
152+
client = RayJobClient(address=dashboard_url, verify=False)
153+
# Try to call a method to trigger the connection and authentication check
154+
client.list_jobs()
155+
assert (
156+
False
157+
), "RayJobClient succeeded without authentication - this should not be possible"
158+
except (
159+
requests.exceptions.JSONDecodeError,
160+
requests.exceptions.HTTPError,
161+
Exception,
162+
):
163+
# Any exception is expected when trying to use the client without auth
164+
pass
165+
166+
assert True, "Job submission without authentication was correctly blocked"
100167

101168
def assert_jobsubmit_withlogin(self, cluster):
102169
auth_token = run_oc_command(["whoami", "--show-token=true"])
103170
ray_dashboard = cluster.cluster_dashboard_uri()
104171
header = {"Authorization": f"Bearer {auth_token}"}
105172
client = RayJobClient(address=ray_dashboard, headers=header, verify=False)
106173

174+
# Verify that no jobs were submitted during the previous unauthenticated test
175+
# This ensures that the authentication check in assert_jobsubmit_withoutLogin actually worked
176+
existing_jobs = client.list_jobs()
177+
if existing_jobs:
178+
job_ids = [
179+
job.job_id if hasattr(job, "job_id") else str(job)
180+
for job in existing_jobs
181+
]
182+
assert False, (
183+
f"Found {len(existing_jobs)} existing job(s) before authenticated submission: {job_ids}. "
184+
"This indicates that the unauthenticated job submission test failed to properly block submission."
185+
)
186+
else:
187+
print(
188+
"Verified: No jobs exist from the previous unauthenticated submission attempt."
189+
)
190+
107191
submission_id = client.submit_job(
108192
entrypoint="python mnist.py",
109193
runtime_env={

0 commit comments

Comments
 (0)