diff --git a/tests/test_vllm_port.py b/tests/test_vllm_port.py new file mode 100644 index 000000000000..ccbb36bf4c06 --- /dev/null +++ b/tests/test_vllm_port.py @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +import os +from unittest.mock import patch + +import pytest + +from vllm.envs import get_vllm_port + + +def test_get_vllm_port_not_set(): + """Test when VLLM_PORT is not set.""" + with patch.dict(os.environ, {}, clear=True): + assert get_vllm_port() is None + + +def test_get_vllm_port_valid(): + """Test when VLLM_PORT is set to a valid integer.""" + with patch.dict(os.environ, {"VLLM_PORT": "5678"}, clear=True): + assert get_vllm_port() == 5678 + + +def test_get_vllm_port_invalid(): + """Test when VLLM_PORT is set to a non-integer value.""" + with (patch.dict(os.environ, {"VLLM_PORT": "abc"}, clear=True), + pytest.raises(ValueError, match="must be a valid integer")): + get_vllm_port() + + +def test_get_vllm_port_uri(): + """Test when VLLM_PORT is set to a URI.""" + with (patch.dict(os.environ, {"VLLM_PORT": "tcp://localhost:5678"}, + clear=True), + pytest.raises(ValueError, match="appears to be a URI")): + get_vllm_port() diff --git a/vllm/envs.py b/vllm/envs.py index fe3fa91fbe33..dc23c8ea5314 100644 --- a/vllm/envs.py +++ b/vllm/envs.py @@ -139,6 +139,39 @@ def maybe_convert_int(value: Optional[str]) -> Optional[int]: return int(value) +def get_vllm_port() -> Optional[int]: + """Get the port from VLLM_PORT environment variable. + + Returns: + The port number as an integer if VLLM_PORT is set, None otherwise. + + Raises: + ValueError: If VLLM_PORT is a URI, suggest k8s service discovery issue. + """ + if 'VLLM_PORT' not in os.environ: + return None + + port = os.getenv('VLLM_PORT', '0') + + try: + return int(port) + except ValueError as err: + from urllib.parse import urlparse + try: + parsed = urlparse(port) + if parsed.scheme: + raise ValueError( + f"VLLM_PORT '{port}' appears to be a URI. " + "This may be caused by a Kubernetes service discovery issue" + "check the warning in: https://docs.vllm.ai/en/stable/serving/env_vars.html" + ) + except Exception: + pass + + raise ValueError( + f"VLLM_PORT '{port}' must be a valid integer") from err + + # The begin-* and end* here are used by the documentation generator # to extract the used env vars. @@ -219,10 +252,8 @@ environment_variables: dict[str, Callable[[], Any]] = { # Note: if VLLM_PORT is set, and some code asks for multiple ports, the # VLLM_PORT will be used as the first port, and the rest will be generated # by incrementing the VLLM_PORT value. - # '0' is used to make mypy happy 'VLLM_PORT': - lambda: int(os.getenv('VLLM_PORT', '0')) - if 'VLLM_PORT' in os.environ else None, + get_vllm_port, # path used for ipc when the frontend api server is running in # multi-processing mode to communicate with the backend engine process.