Skip to content

Commit e62da62

Browse files
authored
Clean up 0.19 compatibility code (#3347)
* Pass job_submissions_limit=1 * Remove dummy ssh_key_pub * Adjust TODO comment * Mark /fleets/create as deprecated * Mark InstanceModel.health_status deferred * Drop deprecated Gateway fields * Drop client excludes * Drop deprecated Azure VMs * Drop deprecated unused model fields * Minor fixes * Fix tests * Revert "Drop deprecated Gateway fields" This reverts commit bf2f18d. * Revert "Fix tests" This reverts commit bfce1cf. * Make deprecated Gateway fields optional
1 parent 0b3d6df commit e62da62

File tree

22 files changed

+45
-286
lines changed

22 files changed

+45
-286
lines changed

docs/docs/guides/server-deployment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ When using [files](../concepts/dev-environments.md#files) or [repos](../concept
228228

229229
### S3
230230

231-
To use S3 for storing uploaded files, set the `DSTACK_SERVER_S3_BUCKET` and `DSTACK_SERVER_BUCKET_REGION` environment variables.
231+
To use S3 for storing uploaded files, set the `DSTACK_SERVER_S3_BUCKET` and `DSTACK_SERVER_S3_BUCKET_REGION` environment variables.
232232
The bucket must be created beforehand. `dstack` won't try to create it.
233233

234234
??? info "Required permissions"

src/dstack/_internal/cli/commands/offer.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ def _command(self, args: argparse.Namespace):
105105
run_spec = RunSpec(
106106
configuration=conf,
107107
profile=profile,
108-
ssh_key_pub="(dummy)", # TODO: Remove since 0.19.40
109108
)
110109

111110
if args.group_by:

src/dstack/_internal/cli/services/configurators/fleet.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
from dstack._internal.core.errors import (
2121
CLIError,
2222
ConfigurationError,
23-
MethodNotAllowedError,
2423
ResourceNotExistsError,
2524
ServerClientError,
26-
URLNotFoundError,
2725
)
2826
from dstack._internal.core.models.common import ApplyAction
2927
from dstack._internal.core.models.configurations import ApplyConfigurationType
@@ -39,7 +37,6 @@
3937
from dstack._internal.utils.common import local_time
4038
from dstack._internal.utils.logging import get_logger
4139
from dstack._internal.utils.ssh import convert_ssh_key_to_pem, generate_public_key, pkey_from_str
42-
from dstack.api._public import Client
4340
from dstack.api.utils import load_profile
4441

4542
logger = get_logger(__name__)
@@ -233,7 +230,7 @@ def _apply_plan_on_old_server(self, plan: FleetPlan, command_args: argparse.Name
233230

234231
try:
235232
with console.status("Applying plan..."):
236-
fleet = _apply_plan(self.api, plan)
233+
fleet = self.api.client.fleets.apply_plan(project_name=self.api.project, plan=plan)
237234
except ServerClientError as e:
238235
raise CLIError(e.msg)
239236
if command_args.detach:
@@ -481,17 +478,3 @@ def _fleet_retrying(fleet: Fleet) -> bool:
481478
return False
482479
active_instances = [i for i in fleet.instances if i.status.is_active()]
483480
return len(active_instances) < fleet.spec.configuration.nodes.min
484-
485-
486-
def _apply_plan(api: Client, plan: FleetPlan) -> Fleet:
487-
try:
488-
return api.client.fleets.apply_plan(
489-
project_name=api.project,
490-
plan=plan,
491-
)
492-
except (URLNotFoundError, MethodNotAllowedError):
493-
# TODO: Remove in 0.20
494-
return api.client.fleets.create(
495-
project_name=api.project,
496-
spec=plan.spec,
497-
)

src/dstack/_internal/core/backends/azure/compute.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,6 @@ def get_image_name(self) -> str:
420420
r"NC(\d+)ads_A100_v4", # NC A100 v4-series [A100 80GB]
421421
r"ND(\d+)asr_v4", # ND A100 v4-series [8xA100 40GB]
422422
r"ND(\d+)amsr_A100_v4", # NDm A100 v4-series [8xA100 80GB]
423-
# Deprecated series
424-
# TODO: Remove after several releases
425-
r"D(\d+)s_v3", # Dsv3-series (general purpose)
426-
r"E(\d+)i?s_v4", # Esv4-series (memory optimized)
427-
r"E(\d+)-(\d+)s_v4", # Esv4-series (constrained vCPU)
428423
]
429424
_SUPPORTED_VM_SERIES_PATTERN = (
430425
"^Standard_(" + "|".join(f"({s})" for s in _SUPPORTED_VM_SERIES_PATTERNS) + ")$"

src/dstack/_internal/core/backends/kubernetes/compute.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
from dstack._internal.core.consts import DSTACK_RUNNER_SSH_PORT
3535
from dstack._internal.core.errors import ComputeError
3636
from dstack._internal.core.models.backends.base import BackendType
37-
38-
# TODO: update import as KNOWN_GPUS becomes public
3937
from dstack._internal.core.models.gateways import (
4038
GatewayComputeConfiguration,
4139
GatewayProvisioningData,

src/dstack/_internal/core/compatibility/fleets.py

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from dstack._internal.core.models.common import IncludeExcludeDictType, IncludeExcludeSetType
44
from dstack._internal.core.models.fleets import ApplyFleetPlanInput, FleetSpec
5-
from dstack._internal.core.models.instances import Instance
65

76

87
def get_get_plan_excludes(fleet_spec: FleetSpec) -> IncludeExcludeDictType:
@@ -22,10 +21,6 @@ def get_apply_plan_excludes(plan_input: ApplyFleetPlanInput) -> IncludeExcludeDi
2221
if current_resource is not None:
2322
current_resource_excludes = {}
2423
apply_plan_excludes["current_resource"] = current_resource_excludes
25-
if all(map(_should_exclude_instance_cpu_arch, current_resource.instances)):
26-
current_resource_excludes["instances"] = {
27-
"__all__": {"instance_type": {"resources": {"cpu_arch"}}}
28-
}
2924
return {"plan": apply_plan_excludes}
3025

3126

@@ -46,35 +41,18 @@ def get_fleet_spec_excludes(fleet_spec: FleetSpec) -> Optional[IncludeExcludeDic
4641
spec_excludes: IncludeExcludeDictType = {}
4742
configuration_excludes: IncludeExcludeDictType = {}
4843
profile_excludes: IncludeExcludeSetType = set()
49-
profile = fleet_spec.profile
50-
if profile.fleets is None:
51-
profile_excludes.add("fleets")
52-
if fleet_spec.configuration.tags is None:
53-
configuration_excludes["tags"] = True
54-
if profile.tags is None:
55-
profile_excludes.add("tags")
56-
if profile.startup_order is None:
57-
profile_excludes.add("startup_order")
58-
if profile.stop_criteria is None:
59-
profile_excludes.add("stop_criteria")
60-
if profile.schedule is None:
61-
profile_excludes.add("schedule")
62-
if (
63-
fleet_spec.configuration.nodes
64-
and fleet_spec.configuration.nodes.min == fleet_spec.configuration.nodes.target
65-
):
66-
configuration_excludes["nodes"] = {"target"}
44+
45+
# Add excludes like this:
46+
#
47+
# if fleet_spec.configuration.tags is None:
48+
# configuration_excludes["tags"] = True
49+
# if fleet_spec.profile.tags is None:
50+
# profile_excludes.add("tags")
51+
6752
if configuration_excludes:
6853
spec_excludes["configuration"] = configuration_excludes
6954
if profile_excludes:
7055
spec_excludes["profile"] = profile_excludes
7156
if spec_excludes:
7257
return spec_excludes
7358
return None
74-
75-
76-
def _should_exclude_instance_cpu_arch(instance: Instance) -> bool:
77-
try:
78-
return instance.instance_type.resources.cpu_arch is None
79-
except AttributeError:
80-
return True

src/dstack/_internal/core/compatibility/gateways.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ def _get_gateway_configuration_excludes(
3030
configuration: GatewayConfiguration,
3131
) -> IncludeExcludeDictType:
3232
configuration_excludes: IncludeExcludeDictType = {}
33-
if configuration.tags is None:
34-
configuration_excludes["tags"] = True
35-
if configuration.router is None:
36-
configuration_excludes["router"] = True
33+
34+
# Add excludes like this:
35+
#
36+
# if configuration.tags is None:
37+
# configuration_excludes["tags"] = True
38+
3739
return configuration_excludes

src/dstack/_internal/core/compatibility/logs.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,4 @@ def get_poll_logs_excludes(request: PollLogsRequest) -> Optional[IncludeExcludeD
1111
clients backward-compatibility with older servers.
1212
"""
1313
excludes: IncludeExcludeDictType = {}
14-
if request.next_token is None:
15-
excludes["next_token"] = True
1614
return excludes if excludes else None
Lines changed: 8 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
from typing import Optional
22

33
from dstack._internal.core.models.common import IncludeExcludeDictType, IncludeExcludeSetType
4-
from dstack._internal.core.models.configurations import LEGACY_REPO_DIR, ServiceConfiguration
5-
from dstack._internal.core.models.runs import ApplyRunPlanInput, JobSpec, JobSubmission, RunSpec
4+
from dstack._internal.core.models.runs import ApplyRunPlanInput, JobSpec, RunSpec
65
from dstack._internal.server.schemas.runs import GetRunPlanRequest, ListRunsRequest
7-
from dstack._internal.settings import FeatureFlags
86

97

108
def get_list_runs_excludes(list_runs_request: ListRunsRequest) -> IncludeExcludeSetType:
11-
excludes = set()
12-
if list_runs_request.include_jobs:
13-
excludes.add("include_jobs")
14-
if list_runs_request.job_submissions_limit is None:
15-
excludes.add("job_submissions_limit")
9+
excludes: IncludeExcludeSetType = set()
1610
return excludes
1711

1812

@@ -29,82 +23,7 @@ def get_apply_plan_excludes(plan: ApplyRunPlanInput) -> Optional[IncludeExcludeD
2923
current_resource = plan.current_resource
3024
if current_resource is not None:
3125
current_resource_excludes: IncludeExcludeDictType = {}
32-
current_resource_excludes["status_message"] = True
33-
if current_resource.deployment_num == 0:
34-
current_resource_excludes["deployment_num"] = True
35-
if current_resource.fleet is None:
36-
current_resource_excludes["fleet"] = True
37-
if current_resource.next_triggered_at is None:
38-
current_resource_excludes["next_triggered_at"] = True
39-
apply_plan_excludes["current_resource"] = current_resource_excludes
4026
current_resource_excludes["run_spec"] = get_run_spec_excludes(current_resource.run_spec)
41-
job_submissions_excludes: IncludeExcludeDictType = {}
42-
current_resource_excludes["jobs"] = {
43-
"__all__": {
44-
"job_spec": get_job_spec_excludes([job.job_spec for job in current_resource.jobs]),
45-
"job_submissions": {"__all__": job_submissions_excludes},
46-
}
47-
}
48-
job_submissions = [js for j in current_resource.jobs for js in j.job_submissions]
49-
if all(map(_should_exclude_job_submission_jpd_cpu_arch, job_submissions)):
50-
job_submissions_excludes["job_provisioning_data"] = {
51-
"instance_type": {"resources": {"cpu_arch"}}
52-
}
53-
jrd_offer_excludes = {}
54-
if any(
55-
js.job_runtime_data and js.job_runtime_data.offer for js in job_submissions
56-
) and all(
57-
not js.job_runtime_data
58-
or not js.job_runtime_data.offer
59-
or not js.job_runtime_data.offer.backend_data
60-
for js in job_submissions
61-
):
62-
jrd_offer_excludes["backend_data"] = True
63-
if all(map(_should_exclude_job_submission_jrd_cpu_arch, job_submissions)):
64-
jrd_offer_excludes["instance"] = {"resources": {"cpu_arch"}}
65-
if jrd_offer_excludes:
66-
job_submissions_excludes["job_runtime_data"] = {"offer": jrd_offer_excludes}
67-
if all(js.exit_status is None for js in job_submissions):
68-
job_submissions_excludes["exit_status"] = True
69-
if all(js.status_message == "" for js in job_submissions):
70-
job_submissions_excludes["status_message"] = True
71-
if all(js.error is None for js in job_submissions):
72-
job_submissions_excludes["error"] = True
73-
if all(js.deployment_num == 0 for js in job_submissions):
74-
job_submissions_excludes["deployment_num"] = True
75-
if all(not js.probes for js in job_submissions):
76-
job_submissions_excludes["probes"] = True
77-
latest_job_submission = current_resource.latest_job_submission
78-
if latest_job_submission is not None:
79-
latest_job_submission_excludes: IncludeExcludeDictType = {}
80-
current_resource_excludes["latest_job_submission"] = latest_job_submission_excludes
81-
if _should_exclude_job_submission_jpd_cpu_arch(latest_job_submission):
82-
latest_job_submission_excludes["job_provisioning_data"] = {
83-
"instance_type": {"resources": {"cpu_arch"}}
84-
}
85-
latest_job_submission_jrd_offer_excludes = {}
86-
if (
87-
latest_job_submission.job_runtime_data
88-
and latest_job_submission.job_runtime_data.offer
89-
and not latest_job_submission.job_runtime_data.offer.backend_data
90-
):
91-
latest_job_submission_jrd_offer_excludes["backend_data"] = True
92-
if _should_exclude_job_submission_jrd_cpu_arch(latest_job_submission):
93-
latest_job_submission_jrd_offer_excludes["instance"] = {"resources": {"cpu_arch"}}
94-
if latest_job_submission_jrd_offer_excludes:
95-
latest_job_submission_excludes["job_runtime_data"] = {
96-
"offer": latest_job_submission_jrd_offer_excludes
97-
}
98-
if latest_job_submission.exit_status is None:
99-
latest_job_submission_excludes["exit_status"] = True
100-
if latest_job_submission.status_message == "":
101-
latest_job_submission_excludes["status_message"] = True
102-
if latest_job_submission.error is None:
103-
latest_job_submission_excludes["error"] = True
104-
if latest_job_submission.deployment_num == 0:
105-
latest_job_submission_excludes["deployment_num"] = True
106-
if not latest_job_submission.probes:
107-
latest_job_submission_excludes["probes"] = True
10827
return {"plan": apply_plan_excludes}
10928

11029

@@ -117,8 +36,6 @@ def get_get_plan_excludes(request: GetRunPlanRequest) -> Optional[IncludeExclude
11736
run_spec_excludes = get_run_spec_excludes(request.run_spec)
11837
if run_spec_excludes is not None:
11938
get_plan_excludes["run_spec"] = run_spec_excludes
120-
if request.max_offers is None:
121-
get_plan_excludes["max_offers"] = True
12239
return get_plan_excludes
12340

12441

@@ -131,53 +48,13 @@ def get_run_spec_excludes(run_spec: RunSpec) -> IncludeExcludeDictType:
13148
spec_excludes: IncludeExcludeDictType = {}
13249
configuration_excludes: IncludeExcludeDictType = {}
13350
profile_excludes: IncludeExcludeSetType = set()
134-
configuration = run_spec.configuration
135-
profile = run_spec.profile
13651

137-
if not FeatureFlags.LEGACY_REPO_DIR_DISABLED:
138-
if run_spec.repo_dir in [None, LEGACY_REPO_DIR]:
139-
spec_excludes["repo_dir"] = True
140-
elif run_spec.repo_dir == "." and configuration.working_dir in [
141-
None,
142-
LEGACY_REPO_DIR,
143-
".",
144-
]:
145-
spec_excludes["repo_dir"] = True
146-
147-
if configuration.fleets is None:
148-
configuration_excludes["fleets"] = True
149-
if profile is not None and profile.fleets is None:
150-
profile_excludes.add("fleets")
151-
if configuration.tags is None:
152-
configuration_excludes["tags"] = True
153-
if profile is not None and profile.tags is None:
154-
profile_excludes.add("tags")
155-
if isinstance(configuration, ServiceConfiguration) and not configuration.rate_limits:
156-
configuration_excludes["rate_limits"] = True
157-
if configuration.shell is None:
158-
configuration_excludes["shell"] = True
159-
if configuration.docker is None:
160-
configuration_excludes["docker"] = True
161-
if configuration.priority is None:
162-
configuration_excludes["priority"] = True
163-
if configuration.startup_order is None:
164-
configuration_excludes["startup_order"] = True
165-
if profile is not None and profile.startup_order is None:
166-
profile_excludes.add("startup_order")
167-
if configuration.stop_criteria is None:
168-
configuration_excludes["stop_criteria"] = True
169-
if isinstance(configuration, ServiceConfiguration) and not configuration.probes:
170-
configuration_excludes["probes"] = True
171-
if profile is not None and profile.stop_criteria is None:
172-
profile_excludes.add("stop_criteria")
173-
if not configuration.files:
174-
configuration_excludes["files"] = True
175-
if not run_spec.file_archives:
176-
spec_excludes["file_archives"] = True
177-
if configuration.schedule is None:
178-
configuration_excludes["schedule"] = True
179-
if profile is not None and profile.schedule is None:
180-
profile_excludes.add("schedule")
52+
# Add excludes like this:
53+
#
54+
# if run_spec.configuration.tags is None:
55+
# configuration_excludes["tags"] = True
56+
# if run_spec.profile is not None and run_spec.profile.tags is None:
57+
# profile_excludes.add("tags")
18158

18259
if configuration_excludes:
18360
spec_excludes["configuration"] = configuration_excludes
@@ -193,34 +70,4 @@ def get_job_spec_excludes(job_specs: list[JobSpec]) -> IncludeExcludeDictType:
19370
clients backward-compatibility with older servers.
19471
"""
19572
spec_excludes: IncludeExcludeDictType = {}
196-
197-
if all(s.repo_code_hash is None for s in job_specs):
198-
spec_excludes["repo_code_hash"] = True
199-
if all(s.repo_data is None for s in job_specs):
200-
spec_excludes["repo_data"] = True
201-
if all(not s.file_archives for s in job_specs):
202-
spec_excludes["file_archives"] = True
203-
if all(s.service_port is None for s in job_specs):
204-
spec_excludes["service_port"] = True
205-
if all(not s.probes for s in job_specs):
206-
spec_excludes["probes"] = True
207-
if all(s.repo_dir in [None, LEGACY_REPO_DIR] for s in job_specs):
208-
spec_excludes["repo_dir"] = True
209-
if all(s.requirements.multinode is None for s in job_specs):
210-
spec_excludes["requirements"] = {"multinode": True}
211-
21273
return spec_excludes
213-
214-
215-
def _should_exclude_job_submission_jpd_cpu_arch(job_submission: JobSubmission) -> bool:
216-
try:
217-
return job_submission.job_provisioning_data.instance_type.resources.cpu_arch is None
218-
except AttributeError:
219-
return True
220-
221-
222-
def _should_exclude_job_submission_jrd_cpu_arch(job_submission: JobSubmission) -> bool:
223-
try:
224-
return job_submission.job_runtime_data.offer.instance.resources.cpu_arch is None
225-
except AttributeError:
226-
return True

src/dstack/_internal/core/compatibility/volumes.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ def _get_volume_configuration_excludes(
2828
configuration: VolumeConfiguration,
2929
) -> IncludeExcludeDictType:
3030
configuration_excludes: IncludeExcludeDictType = {}
31-
if configuration.tags is None:
32-
configuration_excludes["tags"] = True
33-
if configuration.auto_cleanup_duration is None:
34-
configuration_excludes["auto_cleanup_duration"] = True
31+
32+
# Add excludes like this:
33+
#
34+
# if configuration.tags is None:
35+
# configuration_excludes["tags"] = True
36+
3537
return configuration_excludes

0 commit comments

Comments
 (0)