Skip to content

Commit b42fd90

Browse files
committed
feat(urls): warn on partial URL override [AE-2946]
1 parent 904742a commit b42fd90

2 files changed

Lines changed: 142 additions & 0 deletions

File tree

src/runpod_flash/core/urls.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,43 @@ def _endpoint_domain_from_base_url(base_url: str) -> str:
7979

8080

8181
ENDPOINT_DOMAIN: str = _endpoint_domain_from_base_url(RUNPOD_ENDPOINT_URL)
82+
83+
# ---------------------------------------------------------------------------
84+
# Partial-override sanity warning
85+
#
86+
# If a user overrides some URLs but leaves others at their prod defaults, it
87+
# is almost always a misconfiguration — they meant to target a non-prod
88+
# environment but forgot a var. One RuntimeWarning at init; not fatal because
89+
# legitimate mixed setups exist (e.g. dev control plane + prod HAPI).
90+
# ---------------------------------------------------------------------------
91+
92+
_DEFAULTS = {
93+
"RUNPOD_API_BASE_URL": "https://api.runpod.io",
94+
"RUNPOD_ENDPOINT_BASE_URL": "https://api.runpod.ai/v2",
95+
"RUNPOD_REST_API_URL": "https://rest.runpod.io/v1",
96+
"RUNPOD_HAPI_URL": "https://hapi.runpod.net",
97+
"RUNPOD_CONSOLE_URL": "https://console.runpod.io",
98+
}
99+
_resolved = {
100+
"RUNPOD_API_BASE_URL": RUNPOD_API_URL,
101+
"RUNPOD_ENDPOINT_BASE_URL": RUNPOD_ENDPOINT_URL,
102+
"RUNPOD_REST_API_URL": RUNPOD_REST_API_URL,
103+
"RUNPOD_HAPI_URL": RUNPOD_HAPI_URL,
104+
"RUNPOD_CONSOLE_URL": RUNPOD_CONSOLE_URL,
105+
}
106+
_overridden = sorted(
107+
name for name, value in _resolved.items() if value != _DEFAULTS[name].rstrip("/")
108+
)
109+
_at_default = sorted(
110+
name for name, value in _resolved.items() if value == _DEFAULTS[name].rstrip("/")
111+
)
112+
if _overridden and _at_default:
113+
warnings.warn(
114+
"Partial Runpod URL override detected. "
115+
f"Overridden: {_overridden}. Still at default: {_at_default}. "
116+
"This is usually a misconfiguration — set all URLs for the target environment.",
117+
RuntimeWarning,
118+
stacklevel=2,
119+
)
120+
121+
del _DEFAULTS, _resolved, _overridden, _at_default

tests/unit/core/test_urls.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import sys
55
import warnings
66

7+
import pytest
8+
79

810
def _reload_urls_module():
911
"""Reload core.urls so module-level env reads pick up the current env."""
@@ -118,3 +120,103 @@ def test_default_console_when_neither_set(self, monkeypatch):
118120
monkeypatch.delenv("CONSOLE_BASE_URL", raising=False)
119121
mod = _reload_urls_module()
120122
assert mod.RUNPOD_CONSOLE_URL == "https://console.runpod.io"
123+
124+
125+
class TestPartialOverrideWarning:
126+
"""A partial URL override is a common misconfiguration signal."""
127+
128+
@pytest.fixture(autouse=True)
129+
def clear_all_url_env(self, monkeypatch):
130+
for name in (
131+
"RUNPOD_API_BASE_URL",
132+
"RUNPOD_ENDPOINT_BASE_URL",
133+
"RUNPOD_REST_API_URL",
134+
"RUNPOD_HAPI_URL",
135+
"RUNPOD_HAPI_BASE_URL",
136+
"RUNPOD_CONSOLE_URL",
137+
"CONSOLE_BASE_URL",
138+
):
139+
monkeypatch.delenv(name, raising=False)
140+
141+
@pytest.fixture
142+
def prod_runpod_endpoint(self, monkeypatch):
143+
"""Pin runpod.endpoint_url_base to prod default.
144+
145+
``runpod.endpoint_url_base`` is captured once at runpod-package
146+
import time and never re-read, so deleting ``RUNPOD_ENDPOINT_BASE_URL``
147+
from the environment does not reset it. Tests that want the endpoint
148+
URL to look like prod must force it here; otherwise a leaked env var
149+
in the host shell or CI runner makes the resolved endpoint URL
150+
"overridden" and silently corrupts assertions.
151+
"""
152+
import runpod
153+
154+
monkeypatch.setattr(runpod, "endpoint_url_base", "https://api.runpod.ai/v2")
155+
156+
@pytest.fixture
157+
def custom_runpod_endpoint(self, monkeypatch):
158+
"""Pin runpod.endpoint_url_base to a custom dev-like URL.
159+
160+
Same caching caveat as ``prod_runpod_endpoint``: setting
161+
``RUNPOD_ENDPOINT_BASE_URL`` via ``monkeypatch.setenv`` is not
162+
sufficient because ``runpod.endpoint_url_base`` was already cached.
163+
"""
164+
import runpod
165+
166+
monkeypatch.setattr(
167+
runpod, "endpoint_url_base", "https://endpoint.custom.test/v2"
168+
)
169+
170+
def test_no_warning_when_all_at_default(self, prod_runpod_endpoint):
171+
with warnings.catch_warnings(record=True) as captured:
172+
warnings.simplefilter("always")
173+
_reload_urls_module()
174+
assert not any(
175+
issubclass(w.category, RuntimeWarning)
176+
and "Partial Runpod URL override" in str(w.message)
177+
for w in captured
178+
)
179+
180+
def test_warning_when_partially_overridden(self, monkeypatch, prod_runpod_endpoint):
181+
monkeypatch.setenv("RUNPOD_API_BASE_URL", "https://api.custom.test")
182+
183+
with warnings.catch_warnings(record=True) as captured:
184+
warnings.simplefilter("always")
185+
_reload_urls_module()
186+
187+
matches = [
188+
w
189+
for w in captured
190+
if issubclass(w.category, RuntimeWarning)
191+
and "Partial Runpod URL override" in str(w.message)
192+
]
193+
assert matches, "Expected a partial-override RuntimeWarning"
194+
msg = str(matches[0].message)
195+
overridden_section = msg.split("Overridden:")[1].split("Still at default:")[0]
196+
default_section = msg.split("Still at default:")[1]
197+
assert "RUNPOD_API_BASE_URL" in overridden_section
198+
for name in (
199+
"RUNPOD_ENDPOINT_BASE_URL",
200+
"RUNPOD_REST_API_URL",
201+
"RUNPOD_HAPI_URL",
202+
"RUNPOD_CONSOLE_URL",
203+
):
204+
assert name in default_section, f"{name} miscategorized"
205+
206+
def test_no_warning_when_all_overridden(self, monkeypatch, custom_runpod_endpoint):
207+
monkeypatch.setenv("RUNPOD_API_BASE_URL", "https://api.custom.test")
208+
monkeypatch.setenv(
209+
"RUNPOD_ENDPOINT_BASE_URL", "https://endpoint.custom.test/v2"
210+
)
211+
monkeypatch.setenv("RUNPOD_REST_API_URL", "https://rest.custom.test/v1")
212+
monkeypatch.setenv("RUNPOD_HAPI_URL", "https://hapi.custom.test")
213+
monkeypatch.setenv("RUNPOD_CONSOLE_URL", "https://console.custom.test")
214+
215+
with warnings.catch_warnings(record=True) as captured:
216+
warnings.simplefilter("always")
217+
_reload_urls_module()
218+
assert not any(
219+
issubclass(w.category, RuntimeWarning)
220+
and "Partial Runpod URL override" in str(w.message)
221+
for w in captured
222+
)

0 commit comments

Comments
 (0)