[serve] Exclude unset fields from Ray actor options (#23059)

The `schema_to_deployment()` function preserve unset fields with unexpected default argument types. This change excludes unset fields in that function and also changes the dictionaries' default values to empty dicts.
This commit is contained in:
shrekris-anyscale 2022-03-11 08:45:21 -08:00 committed by GitHub
parent a8bed94ed6
commit 665bdbff47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 10 deletions

View file

@ -8,7 +8,7 @@ from ray.serve.utils import DEFAULT
class RayActorOptionsSchema(BaseModel, extra=Extra.forbid): class RayActorOptionsSchema(BaseModel, extra=Extra.forbid):
runtime_env: dict = Field( runtime_env: dict = Field(
default=None, default={},
description=( description=(
"This deployment's runtime_env. working_dir and " "This deployment's runtime_env. working_dir and "
"py_modules may contain only remote URIs." "py_modules may contain only remote URIs."
@ -48,7 +48,7 @@ class RayActorOptionsSchema(BaseModel, extra=Extra.forbid):
ge=0, ge=0,
) )
resources: Dict = Field( resources: Dict = Field(
default=None, description=("The custom resources required by each replica.") default={}, description=("The custom resources required by each replica.")
) )
accelerator_type: str = Field( accelerator_type: str = Field(
default=None, default=None,
@ -341,7 +341,7 @@ def schema_to_deployment(s: DeploymentSchema) -> Deployment:
if s.ray_actor_options is None: if s.ray_actor_options is None:
ray_actor_options = None ray_actor_options = None
else: else:
ray_actor_options = s.ray_actor_options.dict() ray_actor_options = s.ray_actor_options.dict(exclude_unset=True)
return deployment( return deployment(
name=s.name, name=s.name,

View file

@ -61,7 +61,7 @@ class TestRayActorOptionsSchema:
# Test different runtime_env configurations # Test different runtime_env configurations
ray_actor_options_schema = { ray_actor_options_schema = {
"runtime_env": None, "runtime_env": {},
"num_cpus": 0.2, "num_cpus": 0.2,
"num_gpus": 50, "num_gpus": 50,
"memory": 3, "memory": 3,
@ -107,12 +107,12 @@ class TestRayActorOptionsSchema:
# Undefined fields should be forbidden in the schema # Undefined fields should be forbidden in the schema
ray_actor_options_schema = { ray_actor_options_schema = {
"runtime_env": None, "runtime_env": {},
"num_cpus": None, "num_cpus": None,
"num_gpus": None, "num_gpus": None,
"memory": None, "memory": None,
"object_store_memory": None, "object_store_memory": None,
"resources": None, "resources": {},
"accelerator_type": None, "accelerator_type": None,
} }
@ -124,6 +124,15 @@ class TestRayActorOptionsSchema:
with pytest.raises(ValidationError): with pytest.raises(ValidationError):
RayActorOptionsSchema.parse_obj(ray_actor_options_schema) RayActorOptionsSchema.parse_obj(ray_actor_options_schema)
def test_dict_defaults_ray_actor_options(self):
# Dictionary fields should have empty dictionaries as defaults, not None
ray_actor_options_schema = {}
schema = RayActorOptionsSchema.parse_obj(ray_actor_options_schema)
d = schema.dict()
assert d["runtime_env"] == {}
assert d["resources"] == {}
class TestDeploymentSchema: class TestDeploymentSchema:
def get_minimal_deployment_schema(self): def get_minimal_deployment_schema(self):
@ -144,12 +153,12 @@ class TestDeploymentSchema:
"health_check_period_s": None, "health_check_period_s": None,
"health_check_timeout_s": None, "health_check_timeout_s": None,
"ray_actor_options": { "ray_actor_options": {
"runtime_env": None, "runtime_env": {},
"num_cpus": None, "num_cpus": None,
"num_gpus": None, "num_gpus": None,
"memory": None, "memory": None,
"object_store_memory": None, "object_store_memory": None,
"resources": None, "resources": {},
"accelerator_type": None, "accelerator_type": None,
}, },
} }
@ -372,12 +381,12 @@ class TestServeApplicationSchema:
"health_check_period_s": None, "health_check_period_s": None,
"health_check_timeout_s": None, "health_check_timeout_s": None,
"ray_actor_options": { "ray_actor_options": {
"runtime_env": None, "runtime_env": {},
"num_cpus": None, "num_cpus": None,
"num_gpus": None, "num_gpus": None,
"memory": None, "memory": None,
"object_store_memory": None, "object_store_memory": None,
"resources": None, "resources": {},
"accelerator_type": None, "accelerator_type": None,
}, },
}, },
@ -543,6 +552,24 @@ def test_deployment_to_schema_to_deployment():
serve.shutdown() serve.shutdown()
def test_unset_fields_schema_to_deployment_ray_actor_options():
# Ensure unset fields are excluded from ray_actor_options
@serve.deployment(
num_replicas=3,
route_prefix="/hello",
ray_actor_options={},
)
def f():
pass
f._func_or_class = "ray.serve.tests.test_schema.global_f"
deployment = schema_to_deployment(deployment_to_schema(f))
assert len(deployment.ray_actor_options) == 0
def test_serve_application_to_schema_to_serve_application(): def test_serve_application_to_schema_to_serve_application():
@serve.deployment( @serve.deployment(
num_replicas=1, num_replicas=1,