def test_http_root_url(ray_shutdown): @serve.deployment def f(_): pass root_url = "https://my.domain.dev/prefix" port = new_port() os.environ[SERVE_ROOT_URL_ENV_KEY] = root_url serve.start(http_options=dict(port=port)) f.deploy() assert f.url == root_url + "/f" serve.shutdown() ray.shutdown() del os.environ[SERVE_ROOT_URL_ENV_KEY] port = new_port() serve.start(http_options=dict(port=port)) f.deploy() assert f.url != root_url + "/f" assert f.url == f"http://127.0.0.1:{port}/f" serve.shutdown() ray.shutdown() ray.init(runtime_env={"env_vars": {SERVE_ROOT_URL_ENV_KEY: root_url}}) port = new_port() serve.start(http_options=dict(port=port)) f.deploy() assert f.url == root_url + "/f" serve.shutdown() ray.shutdown()
def test_middleware(): from starlette.middleware import Middleware from starlette.middleware.cors import CORSMiddleware port = new_port() serve.start(http_port=port, http_middlewares=[ Middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"]) ]) ray.get(block_until_http_ready.remote(f"http://127.0.0.1:{port}/-/routes")) # Snatched several test cases from Starlette # https://github.com/encode/starlette/blob/master/tests/ # middleware/test_cors.py headers = { "Origin": "https://example.org", "Access-Control-Request-Method": "GET", } root = f"http://localhost:{port}" resp = requests.options(root, headers=headers) assert resp.headers["access-control-allow-origin"] == "*" resp = requests.get(f"{root}/-/routes", headers=headers) assert resp.headers["access-control-allow-origin"] == "*" ray.shutdown()
def test_fixed_number_proxies(ray_cluster): cluster = ray_cluster head_node = cluster.add_node(num_cpus=4) cluster.add_node(num_cpus=4) cluster.add_node(num_cpus=4) ray.init(head_node.address) node_ids = ray.state.node_ids() assert len(node_ids) == 3 with pytest.raises( pydantic.ValidationError, match="you must specify the `fixed_number_replicas` parameter."): serve.start(http_options={ "location": "FixedNumber", }) serve.start(http_options={ "port": new_port(), "location": "FixedNumber", "fixed_number_replicas": 2 }) # Only the controller and two http proxy should be started. controller_handle = _get_global_client()._controller node_to_http_actors = ray.get(controller_handle.get_http_proxies.remote()) assert len(node_to_http_actors) == 2 serve.shutdown() ray.shutdown() cluster.shutdown()
def test_serve_start_different_http_checkpoint_options_warning(caplog): logger = logging.getLogger("ray.serve") caplog.set_level(logging.WARNING, logger="ray.serve") warning_msg = [] class WarningHandler(logging.Handler): def emit(self, record): warning_msg.append(self.format(record)) logger.addHandler(WarningHandler()) ray.init(namespace="serve-test") serve.start(detached=True) # create a different config test_http = dict(host="127.1.1.8", port=new_port()) _, tmp_path = mkstemp() test_ckpt = f"file://{tmp_path}" serve.start(detached=True, http_options=test_http, _checkpoint_path=test_ckpt) for test_config, msg in zip([[test_ckpt], ["host", "port"]], warning_msg): for test_msg in test_config: if "Autoscaling metrics pusher thread" in msg: continue assert test_msg in msg serve.shutdown() ray.shutdown()
def test_serve_start_different_http_checkpoint_options_warning(caplog): import logging from tempfile import mkstemp from ray.serve.utils import logger from ray._private.services import new_port caplog.set_level(logging.WARNING, logger="ray.serve") warning_msg = [] class WarningHandler(logging.Handler): def emit(self, record): warning_msg.append(self.format(record)) logger.addHandler(WarningHandler()) ray.init(namespace="serve-test") serve.start(detached=True) # create a different config test_http = dict(host="127.1.1.8", port=new_port()) _, tmp_path = mkstemp() test_ckpt = f"file://{tmp_path}" serve.start(detached=True, http_options=test_http, _checkpoint_path=test_ckpt) for test_config, msg in zip([[test_ckpt], ["host", "port"]], warning_msg): for test_msg in test_config: assert test_msg in msg serve.shutdown() ray.shutdown()
def test_http_head_only(): cluster = Cluster() head_node = cluster.add_node(num_cpus=4) cluster.add_node(num_cpus=4) ray.init(head_node.address) node_ids = ray.state.node_ids() assert len(node_ids) == 2 client = serve.start(http_options={ "port": new_port(), "location": "HeadOnly" }) # Only the controller and head node actor should be started assert len(ray.actors()) == 2 # They should all be placed on the head node cpu_per_nodes = { r["CPU"] for r in ray.state.state._available_resources_per_node().values() } assert cpu_per_nodes == {2, 4} client.shutdown() ray.shutdown() cluster.shutdown()
def test_http_root_path(ray_shutdown): @serve.deployment def hello(): return "hello" port = new_port() root_path = "/serve" serve.start(http_options=dict(root_path=root_path, port=port)) hello.deploy() # check whether url is prefixed correctly assert hello.url == f"http://127.0.0.1:{port}{root_path}/hello" # check routing works as expected resp = requests.get(hello.url) assert resp.status_code == 200 assert resp.text == "hello" # check advertized routes are prefixed correctly resp = requests.get(f"http://127.0.0.1:{port}{root_path}/-/routes") assert resp.status_code == 200 assert resp.json() == {"/hello": "hello"}