Skip to content

Commit cddb597

Browse files
authored
add suffix to integration tests (#474)
* add suffix to integration tests * dont suffix bundle
1 parent 4af6a0b commit cddb597

File tree

3 files changed

+54
-39
lines changed

3 files changed

+54
-39
lines changed

integration_tests/rest_api_utils.py

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
print(f"Integration tests using gateway {BASE_PATH=}")
1616
DEFAULT_NETWORK_TIMEOUT_SEC = 10
1717

18+
# add suffix to avoid name collisions
19+
SERVICE_IDENTIFIER = os.environ.get("SERVICE_IDENTIFIER", "")
20+
21+
22+
def format_name(name: str) -> str:
23+
return f"{name}-{SERVICE_IDENTIFIER}" if SERVICE_IDENTIFIER else name
24+
25+
1826
# Use the scale-launch-integration-tests id
1927
USER_ID_0 = os.getenv("TEST_USER_ID", "fakeuser")
2028

@@ -97,7 +105,7 @@ def my_model(**keyword_args):
97105

98106
CREATE_ASYNC_MODEL_ENDPOINT_REQUEST_SIMPLE = {
99107
"bundle_name": "model_bundle_simple",
100-
"name": "model-endpoint-simple-async",
108+
"name": format_name("model-endpoint-simple-async"),
101109
"endpoint_type": "async",
102110
"cpus": "0.5",
103111
"memory": "500Mi",
@@ -110,12 +118,12 @@ def my_model(**keyword_args):
110118
}
111119

112120
CREATE_SYNC_MODEL_ENDPOINT_REQUEST_SIMPLE = CREATE_ASYNC_MODEL_ENDPOINT_REQUEST_SIMPLE.copy()
113-
CREATE_SYNC_MODEL_ENDPOINT_REQUEST_SIMPLE["name"] = "model-endpoint-simple-sync"
121+
CREATE_SYNC_MODEL_ENDPOINT_REQUEST_SIMPLE["name"] = format_name("model-endpoint-simple-sync")
114122
CREATE_SYNC_MODEL_ENDPOINT_REQUEST_SIMPLE["endpoint_type"] = "sync"
115123

116124
CREATE_ASYNC_MODEL_ENDPOINT_REQUEST_RUNNABLE_IMAGE = {
117125
"bundle_name": "model_bundle_runnable_image",
118-
"name": "model-endpoint-runnable-image-async",
126+
"name": format_name("model-endpoint-runnable-async"),
119127
"post_inference_hooks": [],
120128
"endpoint_type": "async",
121129
"cpus": "1",
@@ -132,9 +140,9 @@ def my_model(**keyword_args):
132140
CREATE_SYNC_STREAMING_MODEL_ENDPOINT_REQUEST_RUNNABLE_IMAGE = (
133141
CREATE_ASYNC_MODEL_ENDPOINT_REQUEST_RUNNABLE_IMAGE.copy()
134142
)
135-
CREATE_SYNC_STREAMING_MODEL_ENDPOINT_REQUEST_RUNNABLE_IMAGE[
136-
"name"
137-
] = "model-endpoint-runnable-image-sync-streaming"
143+
CREATE_SYNC_STREAMING_MODEL_ENDPOINT_REQUEST_RUNNABLE_IMAGE["name"] = format_name(
144+
"model-endpoint-runnable-sync-streaming"
145+
)
138146
CREATE_SYNC_STREAMING_MODEL_ENDPOINT_REQUEST_RUNNABLE_IMAGE["endpoint_type"] = "streaming"
139147

140148
UPDATE_MODEL_ENDPOINT_REQUEST_SIMPLE = {
@@ -175,7 +183,7 @@ def my_model(**keyword_args):
175183
}
176184

177185
CREATE_DOCKER_IMAGE_BATCH_JOB_BUNDLE_REQUEST: Dict[str, Any] = {
178-
"name": "di_batch_job_bundle_1",
186+
"name": format_name("di_batch_job_bundle_1"),
179187
"image_repository": "model-engine",
180188
"image_tag": "2c1951dfff7159d7d29dd13b4f888e8355f8d51e",
181189
"command": ["jq", ".", "/launch_mount_location/file"],
@@ -188,14 +196,14 @@ def my_model(**keyword_args):
188196
}
189197

190198
CREATE_DOCKER_IMAGE_BATCH_JOB_REQUEST: Dict[str, Any] = {
191-
"docker_image_batch_job_bundle_name": "di_batch_job_bundle_1",
199+
"docker_image_batch_job_bundle_name": format_name("di_batch_job_bundle_1"),
192200
"job_config": {"data": {"to": "mount"}},
193201
"labels": {"team": "infra", "product": "testing"},
194202
"resource_requests": {"cpus": 0.15, "memory": "15Mi"},
195203
}
196204

197205
CREATE_FINE_TUNE_DI_BATCH_JOB_BUNDLE_REQUEST: Dict[str, Any] = {
198-
"name": "fine_tune_di_batch_job_bundle_1",
206+
"name": format_name("fine_tune_di_batch_job_bundle_1"),
199207
"image_repository": "model-engine",
200208
"image_tag": "2c1951dfff7159d7d29dd13b4f888e8355f8d51e",
201209
"command": ["cat", "/launch_mount_location/file"],
@@ -700,9 +708,16 @@ def ensure_n_ready_endpoints_short(n: int, user_id: str):
700708
assert len(ready_endpoints) >= n
701709

702710

703-
def delete_all_endpoints(user_id):
711+
def delete_all_endpoints(user_id: str, delete_suffix_only: bool):
704712
endpoints = list_model_endpoints(user_id)
705713
for i, endpoint in enumerate(endpoints):
714+
if (
715+
delete_suffix_only
716+
and SERVICE_IDENTIFIER
717+
and not endpoint["name"].endswith(SERVICE_IDENTIFIER)
718+
):
719+
continue
720+
706721
response = delete_model_endpoint(endpoint["name"], user_id)
707722
assert response["deleted"]
708723
print(f"[{i + 1}/{len(endpoints)}] Deleted {endpoint=}")
@@ -745,7 +760,9 @@ def ensure_all_async_tasks_success(task_ids: List[str], user_id: str, return_pic
745760
ensure_inference_task_response_is_correct(response, return_pickled)
746761

747762

748-
def delete_existing_endpoints(users: Sequence[str] = DEFAULT_USERS) -> None:
763+
def delete_existing_endpoints(
764+
users: Sequence[str] = DEFAULT_USERS, delete_suffix_only: bool = True
765+
) -> None:
749766
if len(users) == 0:
750767
raise ValueError("Must supply at least one user!")
751768

@@ -778,8 +795,9 @@ def delete_existing_endpoints(users: Sequence[str] = DEFAULT_USERS) -> None:
778795
print(f"[{len({users})}] Deleting all user endpoints...")
779796
try:
780797
for i, u in enumerate(users):
781-
print(f"[{i + 1}/{len(users)}] Deleting all endpoints for user with ID {u}")
782-
delete_all_endpoints(u)
798+
suffix_msg = f" with suffix {SERVICE_IDENTIFIER}" if delete_suffix_only else ""
799+
print(f"[{i + 1}/{len(users)}] Deleting all endpoints{suffix_msg} for user with ID {u}")
800+
delete_all_endpoints(u, delete_suffix_only)
783801
except Exception: # noqa
784802
try:
785803
j: str = json.dumps(all_endpoint_info, indent=2)
@@ -788,5 +806,4 @@ def delete_existing_endpoints(users: Sequence[str] = DEFAULT_USERS) -> None:
788806
barrier: str = "-" * 80
789807
print(f"ERROR! Deletion failed. All endpoint information:\n{barrier}\n{j}\n{barrier}")
790808
raise
791-
792809
time.sleep(15)

integration_tests/test_docs.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# flake8: noqa: W605
33
import importlib.util
44
import os
5-
import random
65
import re
76
from pathlib import Path
87
from textwrap import dedent
@@ -13,6 +12,7 @@
1312
ROOT_DIR = Path(__file__).parent.parent
1413

1514
TEST_SKIP_MAGIC_STRING = "# test='skip'"
15+
SERVICE_IDENTIFIER = os.environ.get("SERVICE_IDENTIFIER", "")
1616

1717

1818
@pytest.fixture
@@ -50,18 +50,12 @@ def env():
5050
setenv.clear()
5151

5252

53-
@pytest.fixture()
54-
def seed() -> int:
55-
"""Returns a random seed between 0 and 999, inclusive."""
56-
return random.randint(0, 999)
57-
58-
5953
@pytest.fixture()
6054
def integration_test_user_id() -> str:
61-
return "62bc820451dbea002b1c5421"
55+
return os.getenv("TEST_USER_ID", "fakeuser")
6256

6357

64-
def modify_source(source: str, seed: int) -> str:
58+
def modify_source(source: str) -> str:
6559
# Adds some custom logic to update code from docs to comply with some requirements.
6660
source = re.sub(r"('team'|\"team\"): ('\w+'|\"\w+\")", r"'team': 'infra'", source)
6761
source = re.sub(
@@ -72,15 +66,21 @@ def modify_source(source: str, seed: int) -> str:
7266

7367
# Add suffix to avoid name collisions
7468
source = re.sub(
75-
r"('endpoint_name'|\"endpoint_name\"): ('(\w+)'|\"(\w+)\")",
76-
f"'endpoint_name': '\g<3>\g<4>-{seed}'",
69+
r"('endpoint_name'|\"endpoint_name\"): ('([\w-]+)'|\"([\w-]+)\")",
70+
rf"'endpoint_name': '\g<3>\g<4>-{SERVICE_IDENTIFIER}'",
7771
source,
7872
)
7973
source = re.sub(
80-
r"endpoint_name=('(\w+)'|\"(\w+)\")",
81-
f"endpoint_name='\g<2>\g<3>-{seed}'",
74+
r"endpoint_name=('([\w-]+)'|\"([\w-]+)\")",
75+
rf"endpoint_name='\g<2>\g<3>-{SERVICE_IDENTIFIER}'",
8276
source,
8377
)
78+
source = re.sub(
79+
r"get_model_endpoint\(\"([\w-]+)\"\)",
80+
rf'get_model_endpoint("\g<1>-{SERVICE_IDENTIFIER}")',
81+
source,
82+
)
83+
8484
source = re.sub(r'"repository": "..."', '"repository": "launch_rearch"', source)
8585
source = re.sub(
8686
r'"tag": "..."', '"tag": "11d9d42047cc9a0c6435b19e5e91bc7e0ad31efc-cpu"', source
@@ -126,15 +126,15 @@ def modify_source(source: str, seed: int) -> str:
126126

127127
@pytest.fixture
128128
def import_execute(request, tmp_work_path: Path):
129-
def _import_execute(module_name: str, source: str, seed: int, rewrite_assertions: bool = False):
129+
def _import_execute(module_name: str, source: str, rewrite_assertions: bool = False):
130130
if rewrite_assertions:
131131
loader = AssertionRewritingHook(config=request.config)
132132
loader.mark_rewrite(module_name)
133133
else:
134134
loader = None
135135

136136
module_path = tmp_work_path / f"{module_name}.py"
137-
modified_source = modify_source(source, seed)
137+
modified_source = modify_source(source)
138138
module_path.write_text(modified_source)
139139
spec = importlib.util.spec_from_file_location("__main__", str(module_path), loader=loader)
140140
module = importlib.util.module_from_spec(spec)
@@ -196,7 +196,6 @@ def test_docs_examples(
196196
source_code,
197197
import_execute,
198198
env,
199-
seed,
200199
integration_test_user_id,
201200
):
202201
if source_code == "__skip__":
@@ -205,6 +204,6 @@ def test_docs_examples(
205204
env("LAUNCH_API_KEY", os.getenv("LAUNCH_TEST_API_KEY", integration_test_user_id))
206205

207206
try:
208-
import_execute(module_name, source_code, seed, True)
207+
import_execute(module_name, source_code, True)
209208
except Exception:
210209
raise

model-engine/requirements-test.txt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
coverage==5.5
2+
diff-cover==7.7.0
3+
frozendict==2.3.4
4+
func-timeout==4.3.5
15
multiprocess==0.70.14
6+
moto==3.1.12
7+
mypy==1.3.0
8+
pylint<3.0.0
29
pytest==7.2.0
310
pytest-asyncio==0.20.1
411
pytest-cov==2.10.0
5-
diff-cover==7.7.0
6-
moto==3.1.12
7-
coverage==5.5
8-
mypy==1.3.0
912
pytest-mypy==0.9.1
1013
pytest-mypy-plugins==1.10.1
11-
pytest-asyncio==0.20.1
1214
pytest-pylint==0.18.0
13-
pylint<3.0.0
1415
types-cachetools==5.3.0.5
1516
types-croniter==1.4.0.0
1617
types-PyYAML==6.0.7
@@ -23,5 +24,3 @@ types-toml==0.10.8
2324
types-ujson==5.5.0
2425
types-urllib3==1.26.14
2526
types-waitress==2.1.4
26-
frozendict==2.3.4
27-
func-timeout==4.3.5

0 commit comments

Comments
 (0)