async def get_all_deployment_statuses(self, req: Request) -> Response: serve_application_status_schema = serve_application_status_to_schema( get_deployment_statuses()) return Response( text=serve_application_status_schema.json(), content_type="application/json", )
def run(self, logger: Union[Logger, _CliLogger] = logger): """Deploys all deployments in this Application and logs status. This function keeps looping and printing status, so it must be manually killed (e.g. using ctrl-C). When it recieves a kill signal, it tears down all deployments that it deployed. If there are no deployments left, it also shuts down the rest of Serve, including the controller. This is meant to help interactive development. Args: logger: Any Python object that implements the standard logger interface. """ try: serve.start(detached=True) self.deploy() logger.info("\nDeployed successfully!\n") while True: statuses = serve_application_status_to_schema( get_deployment_statuses() ).json(indent=4) logger.info(f"{statuses}") time.sleep(10) except KeyboardInterrupt: logger.info("Got SIGINT (KeyboardInterrupt). Removing deployments.") for deployment in self._deployments.values(): deployment.delete() if len(serve.list_deployments()) == 0: logger.info("No deployments left. Shutting down Serve.") serve.shutdown() sys.exit()
def run( config_or_import_path: str, runtime_env: str, runtime_env_json: str, working_dir: str, app_dir: str, address: str, host: str, port: int, blocking: bool, ): sys.path.insert(0, app_dir) final_runtime_env = parse_runtime_env_args( runtime_env=runtime_env, runtime_env_json=runtime_env_json, working_dir=working_dir, ) app_or_node = None if pathlib.Path(config_or_import_path).is_file(): config_path = config_or_import_path cli_logger.print(f"Loading app from config file: '{config_path}'.") with open(config_path, "r") as config_file: app_or_node = Application.from_yaml(config_file) else: import_path = config_or_import_path cli_logger.print(f"Loading app from import path: '{import_path}'.") app_or_node = import_attr(import_path) # Setting the runtime_env here will set defaults for the deployments. ray.init(address=address, namespace="serve", runtime_env=final_runtime_env) try: serve.run(app_or_node, host=host, port=port) cli_logger.success("Deployed successfully!\n") if blocking: while True: statuses = serve_application_status_to_schema( get_deployment_statuses() ).json(indent=4) cli_logger.info(f"{statuses}") time.sleep(10) except KeyboardInterrupt: cli_logger.info("Got KeyboardInterrupt, shutting down...") serve.shutdown() sys.exit()
def test_serve_application_to_schema_to_serve_application(): @serve.deployment( num_replicas=1, route_prefix="/hello", ) def f1(): # The body of this function doesn't matter. See the comment in # test_deployment_to_schema_to_deployment. pass @serve.deployment( num_replicas=2, route_prefix="/hi", ) def f2(): pass f1._func_or_class = "ray.dashboard.modules.serve.tests.test_schema.global_f" f2._func_or_class = "ray.dashboard.modules.serve.tests.test_schema.global_f" deployments = schema_to_serve_application( serve_application_to_schema([f1, f2])) assert deployments[0].num_replicas == 1 assert deployments[0].route_prefix == "/hello" assert deployments[1].num_replicas == 2 assert deployments[1].route_prefix == "/hi" serve.start() deployments[0].deploy() deployments[1].deploy() assert ray.get(deployments[0].get_handle().remote()) == "Hello world!" assert requests.get("http://localhost:8000/hello").text == "Hello world!" assert ray.get(deployments[1].get_handle().remote()) == "Hello world!" assert requests.get("http://localhost:8000/hi").text == "Hello world!" # Check statuses statuses = serve_application_status_to_schema( get_deployment_statuses()).statuses deployment_names = {"f1", "f2"} for deployment_status in statuses: assert deployment_status.status in {"UPDATING", "HEALTHY"} assert deployment_status.name in deployment_names deployment_names.remove(deployment_status.name) assert len(deployment_names) == 0 serve.shutdown()
def test_status_schema_helpers(): @serve.deployment( num_replicas=1, route_prefix="/hello", ) def f1(): # The body of this function doesn't matter. See the comment in # test_deployment_to_schema_to_deployment. pass @serve.deployment( num_replicas=2, route_prefix="/hi", ) def f2(): pass f1._func_or_class = "ray.serve.tests.test_schema.global_f" f2._func_or_class = "ray.serve.tests.test_schema.global_f" serve.start() f1.deploy() f2.deploy() # Check statuses statuses = serve_application_status_to_schema( get_deployment_statuses()).statuses deployment_names = {"f1", "f2"} for deployment_status in statuses: assert deployment_status.status in {"UPDATING", "HEALTHY"} assert deployment_status.name in deployment_names deployment_names.remove(deployment_status.name) assert len(deployment_names) == 0 serve.shutdown()