def test_deploy_app_overwrite_apps(self, client: ServeControllerClient): """Check that overwriting a live app with a new one works.""" # Launch first graph. Its driver's route_prefix should be "/". test_config_1 = ServeApplicationSchema.parse_obj( { "import_path": "ray.serve.tests.test_config_files.world.DagNode", } ) client.deploy_app(test_config_1) wait_for_condition( lambda: requests.get("http://localhost:8000/").text == "wonderful world" ) # Launch second graph. Its driver's route_prefix should also be "/". # "/" should lead to the new driver. test_config_2 = ServeApplicationSchema.parse_obj( { "import_path": "ray.serve.tests.test_config_files.pizza.serve_dag", } ) client.deploy_app(test_config_2) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "4 pizzas please!" )
def test_deploy_app_runtime_env(self, client: ServeControllerClient): config_template = { "import_path": "conditional_dag.serve_dag", "runtime_env": { "working_dir": ( "https://github.com/ray-project/test_dag/archive/" "76a741f6de31df78411b1f302071cde46f098418.zip" ) }, } config1 = ServeApplicationSchema.parse_obj(config_template) client.deploy_app(config1) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "0 pizzas please!" ) # Override the configuration config_template["deployments"] = [ { "name": "Adder", "ray_actor_options": { "runtime_env": {"env_vars": {"override_increment": "1"}} }, } ] config2 = ServeApplicationSchema.parse_obj(config_template) client.deploy_app(config2) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "3 pizzas please!" )
def test_deploy_app_update_timestamp(self, client: ServeControllerClient): assert client.get_serve_status().app_status.deployment_timestamp == 0 config = ServeApplicationSchema.parse_obj(self.get_test_config()) client.deploy_app(config) assert client.get_serve_status().app_status.deployment_timestamp > 0 first_deploy_time = client.get_serve_status().app_status.deployment_timestamp time.sleep(0.1) config = self.get_test_config() config["deployments"] = [ { "name": "Adder", "num_replicas": 2, }, ] client.deploy_app(ServeApplicationSchema.parse_obj(config)) assert ( client.get_serve_status().app_status.deployment_timestamp > first_deploy_time ) assert client.get_serve_status().app_status.status in { ApplicationStatus.DEPLOYING, ApplicationStatus.RUNNING, }
def test_deploy_app_update_config(self, client: ServeControllerClient): config = ServeApplicationSchema.parse_obj(self.get_test_config()) client.deploy_app(config) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "4 pizzas please!" ) config = self.get_test_config() config["deployments"] = [ { "name": "Adder", "user_config": { "increment": -1, }, }, ] client.deploy_app(ServeApplicationSchema.parse_obj(config)) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "1 pizzas please!" )
def test_deploy_app_with_overriden_config(self, client: ServeControllerClient): config = self.get_test_config() config["deployments"] = [ { "name": "Multiplier", "user_config": { "factor": 4, }, }, { "name": "Adder", "user_config": { "increment": 5, }, }, ] client.deploy_app(ServeApplicationSchema.parse_obj(config)) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 0]).json() == "5 pizzas please!" ) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["MUL", 2]).json() == "8 pizzas please!" )
def test_deploy_app_update_num_replicas(self, client: ServeControllerClient): config = ServeApplicationSchema.parse_obj(self.get_test_config()) client.deploy_app(config) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2] ).json() == "4 pizzas please!") wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["MUL", 3] ).json() == "9 pizzas please!") actors = ray.util.list_named_actors(all_namespaces=True) config = self.get_test_config() config["deployments"] = [ { "name": "Adder", "num_replicas": 2, "user_config": { "increment": 0, }, "ray_actor_options": { "num_cpus": 0.1 }, }, { "name": "Multiplier", "num_replicas": 3, "user_config": { "factor": 0, }, "ray_actor_options": { "num_cpus": 0.1 }, }, ] client.deploy_app(ServeApplicationSchema.parse_obj(config)) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2] ).json() == "2 pizzas please!") wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["MUL", 3] ).json() == "0 pizzas please!") wait_for_condition( lambda: client.get_serve_status().app_status.status == ApplicationStatus.RUNNING, timeout=15, ) updated_actors = ray.util.list_named_actors(all_namespaces=True) assert len(updated_actors) == len(actors) + 3
def test_deploy_app_basic(self, client: ServeControllerClient): config = ServeApplicationSchema.parse_obj(self.get_test_config()) client.deploy_app(config) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2] ).json() == "4 pizzas please!") wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["MUL", 3] ).json() == "9 pizzas please!")
def test_controller_recover_and_deploy(self, client: ServeControllerClient): """Ensure that in-progress deploy can finish even after controller dies.""" config = ServeApplicationSchema.parse_obj(self.get_test_config()) client.deploy_app(config) # Wait for app to deploy wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "4 pizzas please!" ) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["MUL", 3]).json() == "9 pizzas please!" ) deployment_timestamp = client.get_serve_status().app_status.deployment_timestamp # Delete all deployments, but don't update config client.delete_deployments( ["Router", "Multiplier", "Adder", "create_order", "DAGDriver"] ) ray.kill(client._controller, no_restart=False) # When controller restarts, it should redeploy config automatically wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["ADD", 2]).json() == "4 pizzas please!" ) wait_for_condition( lambda: requests.post("http://localhost:8000/", json=["MUL", 3]).json() == "9 pizzas please!" ) assert ( deployment_timestamp == client.get_serve_status().app_status.deployment_timestamp ) serve.shutdown() client = serve.start(detached=True) # Ensure config checkpoint has been deleted assert client.get_serve_status().app_status.deployment_timestamp == 0