dstack 0.18.44__py3-none-any.whl → 0.19.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dstack might be problematic. Click here for more details.

Files changed (267) hide show
  1. dstack/_internal/cli/commands/gateway.py +15 -3
  2. dstack/_internal/cli/commands/logs.py +0 -22
  3. dstack/_internal/cli/commands/stats.py +8 -17
  4. dstack/_internal/cli/main.py +1 -5
  5. dstack/_internal/cli/services/configurators/fleet.py +4 -39
  6. dstack/_internal/cli/services/configurators/run.py +22 -21
  7. dstack/_internal/cli/services/profile.py +34 -83
  8. dstack/_internal/cli/utils/gateway.py +1 -1
  9. dstack/_internal/core/backends/__init__.py +56 -39
  10. dstack/_internal/core/backends/aws/__init__.py +0 -25
  11. dstack/_internal/core/backends/aws/auth.py +1 -10
  12. dstack/_internal/core/backends/aws/backend.py +26 -0
  13. dstack/_internal/core/backends/aws/compute.py +20 -45
  14. dstack/_internal/{server/services/backends/configurators/aws.py → core/backends/aws/configurator.py} +46 -85
  15. dstack/_internal/core/backends/aws/models.py +135 -0
  16. dstack/_internal/core/backends/aws/resources.py +1 -1
  17. dstack/_internal/core/backends/azure/__init__.py +0 -20
  18. dstack/_internal/core/backends/azure/auth.py +2 -11
  19. dstack/_internal/core/backends/azure/backend.py +21 -0
  20. dstack/_internal/core/backends/azure/compute.py +13 -27
  21. dstack/_internal/{server/services/backends/configurators/azure.py → core/backends/azure/configurator.py} +141 -210
  22. dstack/_internal/core/backends/azure/models.py +89 -0
  23. dstack/_internal/core/backends/base/__init__.py +0 -12
  24. dstack/_internal/core/backends/base/backend.py +18 -0
  25. dstack/_internal/core/backends/base/compute.py +153 -33
  26. dstack/_internal/core/backends/base/configurator.py +105 -0
  27. dstack/_internal/core/backends/base/models.py +14 -0
  28. dstack/_internal/core/backends/configurators.py +138 -0
  29. dstack/_internal/core/backends/cudo/__init__.py +0 -15
  30. dstack/_internal/core/backends/cudo/backend.py +16 -0
  31. dstack/_internal/core/backends/cudo/compute.py +8 -26
  32. dstack/_internal/core/backends/cudo/configurator.py +72 -0
  33. dstack/_internal/core/backends/cudo/models.py +37 -0
  34. dstack/_internal/core/backends/datacrunch/__init__.py +0 -15
  35. dstack/_internal/core/backends/datacrunch/backend.py +16 -0
  36. dstack/_internal/core/backends/datacrunch/compute.py +8 -25
  37. dstack/_internal/core/backends/datacrunch/configurator.py +66 -0
  38. dstack/_internal/core/backends/datacrunch/models.py +38 -0
  39. dstack/_internal/core/{models/backends/dstack.py → backends/dstack/models.py} +7 -7
  40. dstack/_internal/core/backends/gcp/__init__.py +0 -16
  41. dstack/_internal/core/backends/gcp/auth.py +2 -11
  42. dstack/_internal/core/backends/gcp/backend.py +17 -0
  43. dstack/_internal/core/backends/gcp/compute.py +13 -43
  44. dstack/_internal/{server/services/backends/configurators/gcp.py → core/backends/gcp/configurator.py} +46 -103
  45. dstack/_internal/core/backends/gcp/models.py +125 -0
  46. dstack/_internal/core/backends/kubernetes/__init__.py +0 -15
  47. dstack/_internal/core/backends/kubernetes/backend.py +16 -0
  48. dstack/_internal/core/backends/kubernetes/compute.py +16 -5
  49. dstack/_internal/core/backends/kubernetes/configurator.py +55 -0
  50. dstack/_internal/core/backends/kubernetes/models.py +72 -0
  51. dstack/_internal/core/backends/lambdalabs/__init__.py +0 -16
  52. dstack/_internal/core/backends/lambdalabs/backend.py +17 -0
  53. dstack/_internal/core/backends/lambdalabs/compute.py +7 -28
  54. dstack/_internal/core/backends/lambdalabs/configurator.py +82 -0
  55. dstack/_internal/core/backends/lambdalabs/models.py +37 -0
  56. dstack/_internal/core/backends/local/__init__.py +0 -13
  57. dstack/_internal/core/backends/local/backend.py +14 -0
  58. dstack/_internal/core/backends/local/compute.py +16 -2
  59. dstack/_internal/core/backends/models.py +128 -0
  60. dstack/_internal/core/backends/oci/__init__.py +0 -15
  61. dstack/_internal/core/backends/oci/auth.py +1 -5
  62. dstack/_internal/core/backends/oci/backend.py +16 -0
  63. dstack/_internal/core/backends/oci/compute.py +9 -23
  64. dstack/_internal/{server/services/backends/configurators/oci.py → core/backends/oci/configurator.py} +40 -85
  65. dstack/_internal/core/{models/backends/oci.py → backends/oci/models.py} +24 -25
  66. dstack/_internal/core/backends/oci/region.py +1 -1
  67. dstack/_internal/core/backends/runpod/__init__.py +0 -15
  68. dstack/_internal/core/backends/runpod/backend.py +16 -0
  69. dstack/_internal/core/backends/runpod/compute.py +7 -3
  70. dstack/_internal/core/backends/runpod/configurator.py +59 -0
  71. dstack/_internal/core/backends/runpod/models.py +54 -0
  72. dstack/_internal/core/backends/template/__init__.py +0 -0
  73. dstack/_internal/core/backends/tensordock/__init__.py +0 -15
  74. dstack/_internal/core/backends/tensordock/backend.py +16 -0
  75. dstack/_internal/core/backends/tensordock/compute.py +8 -27
  76. dstack/_internal/core/backends/tensordock/configurator.py +68 -0
  77. dstack/_internal/core/backends/tensordock/models.py +38 -0
  78. dstack/_internal/core/backends/vastai/__init__.py +0 -15
  79. dstack/_internal/core/backends/vastai/backend.py +16 -0
  80. dstack/_internal/core/backends/vastai/compute.py +2 -2
  81. dstack/_internal/core/backends/vastai/configurator.py +66 -0
  82. dstack/_internal/core/backends/vastai/models.py +37 -0
  83. dstack/_internal/core/backends/vultr/__init__.py +0 -15
  84. dstack/_internal/core/backends/vultr/backend.py +16 -0
  85. dstack/_internal/core/backends/vultr/compute.py +10 -24
  86. dstack/_internal/core/backends/vultr/configurator.py +64 -0
  87. dstack/_internal/core/backends/vultr/models.py +34 -0
  88. dstack/_internal/core/models/backends/__init__.py +0 -184
  89. dstack/_internal/core/models/backends/base.py +0 -19
  90. dstack/_internal/core/models/configurations.py +20 -15
  91. dstack/_internal/core/models/envs.py +4 -3
  92. dstack/_internal/core/models/fleets.py +17 -22
  93. dstack/_internal/core/models/gateways.py +3 -3
  94. dstack/_internal/core/models/instances.py +24 -0
  95. dstack/_internal/core/models/profiles.py +41 -46
  96. dstack/_internal/core/models/projects.py +1 -1
  97. dstack/_internal/core/models/repos/base.py +0 -5
  98. dstack/_internal/core/models/repos/local.py +3 -3
  99. dstack/_internal/core/models/repos/remote.py +26 -12
  100. dstack/_internal/core/models/repos/virtual.py +1 -1
  101. dstack/_internal/core/models/resources.py +45 -76
  102. dstack/_internal/core/models/runs.py +17 -19
  103. dstack/_internal/core/models/volumes.py +1 -3
  104. dstack/_internal/core/services/profiles.py +7 -16
  105. dstack/_internal/core/services/repos.py +0 -4
  106. dstack/_internal/server/app.py +0 -3
  107. dstack/_internal/server/background/tasks/process_gateways.py +4 -8
  108. dstack/_internal/server/background/tasks/process_instances.py +14 -9
  109. dstack/_internal/server/background/tasks/process_metrics.py +1 -1
  110. dstack/_internal/server/background/tasks/process_placement_groups.py +4 -1
  111. dstack/_internal/server/background/tasks/process_prometheus_metrics.py +1 -1
  112. dstack/_internal/server/background/tasks/process_running_jobs.py +14 -5
  113. dstack/_internal/server/background/tasks/process_submitted_jobs.py +16 -37
  114. dstack/_internal/server/background/tasks/process_volumes.py +5 -2
  115. dstack/_internal/server/migrations/versions/7bc2586e8b9e_make_instancemodel_pool_id_optional.py +36 -0
  116. dstack/_internal/server/migrations/versions/bc8ca4a505c6_store_backendtype_as_string.py +171 -0
  117. dstack/_internal/server/models.py +48 -9
  118. dstack/_internal/server/routers/backends.py +14 -23
  119. dstack/_internal/server/routers/instances.py +3 -4
  120. dstack/_internal/server/routers/metrics.py +10 -8
  121. dstack/_internal/server/routers/prometheus.py +1 -1
  122. dstack/_internal/server/routers/repos.py +1 -2
  123. dstack/_internal/server/routers/runs.py +13 -59
  124. dstack/_internal/server/schemas/gateways.py +14 -23
  125. dstack/_internal/server/schemas/projects.py +7 -2
  126. dstack/_internal/server/schemas/repos.py +2 -38
  127. dstack/_internal/server/schemas/runner.py +1 -0
  128. dstack/_internal/server/schemas/runs.py +1 -24
  129. dstack/_internal/server/services/backends/__init__.py +85 -158
  130. dstack/_internal/server/services/config.py +52 -576
  131. dstack/_internal/server/services/fleets.py +8 -103
  132. dstack/_internal/server/services/gateways/__init__.py +12 -4
  133. dstack/_internal/server/services/{pools.py → instances.py} +22 -329
  134. dstack/_internal/server/services/jobs/__init__.py +9 -6
  135. dstack/_internal/server/services/jobs/configurators/base.py +16 -0
  136. dstack/_internal/server/services/jobs/configurators/dev.py +9 -1
  137. dstack/_internal/server/services/jobs/configurators/extensions/cursor.py +42 -0
  138. dstack/_internal/server/services/metrics.py +39 -13
  139. dstack/_internal/server/services/offers.py +1 -1
  140. dstack/_internal/server/services/projects.py +23 -14
  141. dstack/_internal/server/services/prometheus.py +176 -18
  142. dstack/_internal/server/services/runs.py +24 -16
  143. dstack/_internal/server/services/volumes.py +8 -4
  144. dstack/_internal/server/statics/index.html +1 -1
  145. dstack/_internal/server/statics/{main-4eb116b97819badd1e2c.js → main-4a0fe83e84574654e397.js} +18 -14
  146. dstack/_internal/server/statics/{main-4eb116b97819badd1e2c.js.map → main-4a0fe83e84574654e397.js.map} +1 -1
  147. dstack/_internal/server/testing/common.py +58 -32
  148. dstack/_internal/utils/json_schema.py +6 -0
  149. dstack/_internal/utils/ssh.py +2 -1
  150. dstack/api/__init__.py +4 -0
  151. dstack/api/_public/__init__.py +16 -20
  152. dstack/api/_public/backends.py +1 -1
  153. dstack/api/_public/repos.py +36 -36
  154. dstack/api/_public/runs.py +167 -83
  155. dstack/api/server/__init__.py +11 -13
  156. dstack/api/server/_backends.py +12 -16
  157. dstack/api/server/_fleets.py +15 -57
  158. dstack/api/server/_gateways.py +3 -14
  159. dstack/api/server/_repos.py +1 -4
  160. dstack/api/server/_runs.py +21 -100
  161. dstack/api/server/_volumes.py +10 -5
  162. dstack/version.py +1 -1
  163. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/METADATA +1 -1
  164. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/RECORD +218 -204
  165. tests/_internal/cli/services/configurators/test_profile.py +6 -6
  166. tests/_internal/core/backends/aws/test_configurator.py +35 -0
  167. tests/_internal/core/backends/aws/test_resources.py +1 -1
  168. tests/_internal/core/backends/azure/test_configurator.py +61 -0
  169. tests/_internal/core/backends/cudo/__init__.py +0 -0
  170. tests/_internal/core/backends/cudo/test_configurator.py +37 -0
  171. tests/_internal/core/backends/datacrunch/__init__.py +0 -0
  172. tests/_internal/core/backends/datacrunch/test_configurator.py +17 -0
  173. tests/_internal/core/backends/gcp/test_configurator.py +42 -0
  174. tests/_internal/core/backends/kubernetes/test_configurator.py +43 -0
  175. tests/_internal/core/backends/lambdalabs/__init__.py +0 -0
  176. tests/_internal/core/backends/lambdalabs/test_configurator.py +38 -0
  177. tests/_internal/core/backends/oci/test_configurator.py +55 -0
  178. tests/_internal/core/backends/runpod/__init__.py +0 -0
  179. tests/_internal/core/backends/runpod/test_configurator.py +33 -0
  180. tests/_internal/core/backends/tensordock/__init__.py +0 -0
  181. tests/_internal/core/backends/tensordock/test_configurator.py +38 -0
  182. tests/_internal/core/backends/vastai/__init__.py +0 -0
  183. tests/_internal/core/backends/vastai/test_configurator.py +33 -0
  184. tests/_internal/core/backends/vultr/__init__.py +0 -0
  185. tests/_internal/core/backends/vultr/test_configurator.py +33 -0
  186. tests/_internal/server/background/tasks/test_process_gateways.py +4 -0
  187. tests/_internal/server/background/tasks/test_process_instances.py +49 -48
  188. tests/_internal/server/background/tasks/test_process_metrics.py +0 -3
  189. tests/_internal/server/background/tasks/test_process_placement_groups.py +2 -0
  190. tests/_internal/server/background/tasks/test_process_prometheus_metrics.py +0 -3
  191. tests/_internal/server/background/tasks/test_process_running_jobs.py +0 -21
  192. tests/_internal/server/background/tasks/test_process_runs.py +8 -22
  193. tests/_internal/server/background/tasks/test_process_submitted_jobs.py +3 -40
  194. tests/_internal/server/background/tasks/test_process_submitted_volumes.py +2 -0
  195. tests/_internal/server/background/tasks/test_process_terminating_jobs.py +10 -15
  196. tests/_internal/server/routers/test_backends.py +6 -764
  197. tests/_internal/server/routers/test_fleets.py +0 -26
  198. tests/_internal/server/routers/test_gateways.py +27 -3
  199. tests/_internal/server/routers/test_instances.py +0 -10
  200. tests/_internal/server/routers/test_metrics.py +27 -0
  201. tests/_internal/server/routers/test_projects.py +56 -0
  202. tests/_internal/server/routers/test_prometheus.py +116 -27
  203. tests/_internal/server/routers/test_repos.py +0 -15
  204. tests/_internal/server/routers/test_runs.py +4 -219
  205. tests/_internal/server/routers/test_volumes.py +2 -3
  206. tests/_internal/server/services/backends/__init__.py +0 -0
  207. tests/_internal/server/services/jobs/configurators/test_task.py +35 -0
  208. tests/_internal/server/services/test_config.py +7 -4
  209. tests/_internal/server/services/test_fleets.py +1 -4
  210. tests/_internal/server/services/{test_pools.py → test_instances.py} +11 -49
  211. tests/_internal/server/services/test_metrics.py +9 -5
  212. tests/_internal/server/services/test_repos.py +1 -14
  213. tests/_internal/server/services/test_runs.py +0 -4
  214. dstack/_internal/cli/commands/pool.py +0 -581
  215. dstack/_internal/cli/commands/run.py +0 -75
  216. dstack/_internal/core/backends/aws/config.py +0 -18
  217. dstack/_internal/core/backends/azure/config.py +0 -12
  218. dstack/_internal/core/backends/base/config.py +0 -5
  219. dstack/_internal/core/backends/cudo/config.py +0 -9
  220. dstack/_internal/core/backends/datacrunch/config.py +0 -9
  221. dstack/_internal/core/backends/gcp/config.py +0 -22
  222. dstack/_internal/core/backends/kubernetes/config.py +0 -6
  223. dstack/_internal/core/backends/lambdalabs/config.py +0 -9
  224. dstack/_internal/core/backends/nebius/__init__.py +0 -15
  225. dstack/_internal/core/backends/nebius/api_client.py +0 -319
  226. dstack/_internal/core/backends/nebius/compute.py +0 -220
  227. dstack/_internal/core/backends/nebius/config.py +0 -6
  228. dstack/_internal/core/backends/nebius/types.py +0 -37
  229. dstack/_internal/core/backends/oci/config.py +0 -6
  230. dstack/_internal/core/backends/runpod/config.py +0 -17
  231. dstack/_internal/core/backends/tensordock/config.py +0 -9
  232. dstack/_internal/core/backends/vastai/config.py +0 -6
  233. dstack/_internal/core/backends/vultr/config.py +0 -9
  234. dstack/_internal/core/models/backends/aws.py +0 -86
  235. dstack/_internal/core/models/backends/azure.py +0 -68
  236. dstack/_internal/core/models/backends/cudo.py +0 -43
  237. dstack/_internal/core/models/backends/datacrunch.py +0 -44
  238. dstack/_internal/core/models/backends/gcp.py +0 -67
  239. dstack/_internal/core/models/backends/kubernetes.py +0 -40
  240. dstack/_internal/core/models/backends/lambdalabs.py +0 -43
  241. dstack/_internal/core/models/backends/nebius.py +0 -54
  242. dstack/_internal/core/models/backends/runpod.py +0 -42
  243. dstack/_internal/core/models/backends/tensordock.py +0 -44
  244. dstack/_internal/core/models/backends/vastai.py +0 -43
  245. dstack/_internal/core/models/backends/vultr.py +0 -40
  246. dstack/_internal/core/models/pools.py +0 -43
  247. dstack/_internal/server/routers/pools.py +0 -142
  248. dstack/_internal/server/schemas/pools.py +0 -38
  249. dstack/_internal/server/services/backends/configurators/base.py +0 -72
  250. dstack/_internal/server/services/backends/configurators/cudo.py +0 -87
  251. dstack/_internal/server/services/backends/configurators/datacrunch.py +0 -79
  252. dstack/_internal/server/services/backends/configurators/kubernetes.py +0 -63
  253. dstack/_internal/server/services/backends/configurators/lambdalabs.py +0 -98
  254. dstack/_internal/server/services/backends/configurators/nebius.py +0 -85
  255. dstack/_internal/server/services/backends/configurators/runpod.py +0 -67
  256. dstack/_internal/server/services/backends/configurators/tensordock.py +0 -82
  257. dstack/_internal/server/services/backends/configurators/vastai.py +0 -80
  258. dstack/_internal/server/services/backends/configurators/vultr.py +0 -80
  259. dstack/api/_public/pools.py +0 -41
  260. dstack/api/_public/resources.py +0 -105
  261. dstack/api/server/_pools.py +0 -63
  262. tests/_internal/server/routers/test_pools.py +0 -612
  263. /dstack/_internal/{server/services/backends/configurators → core/backends/dstack}/__init__.py +0 -0
  264. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/LICENSE.md +0 -0
  265. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/WHEEL +0 -0
  266. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/entry_points.txt +0 -0
  267. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/top_level.txt +0 -0
@@ -1,30 +1,22 @@
1
- from pathlib import Path
2
- from typing import Dict, List, Literal, Optional, Union
1
+ from typing import List, Optional
3
2
 
4
3
  import yaml
5
- from pydantic import BaseModel, Field, ValidationError, root_validator
4
+ from pydantic import Field, ValidationError
6
5
  from sqlalchemy.ext.asyncio import AsyncSession
7
6
  from typing_extensions import Annotated
8
7
 
9
- from dstack._internal.core.backends.runpod.config import RUNPOD_COMMUNITY_CLOUD_DEFAULT
8
+ import dstack._internal.core.backends.configurators
9
+ from dstack._internal.core.backends.models import (
10
+ AnyBackendConfigWithCreds,
11
+ AnyBackendFileConfigWithCreds,
12
+ BackendInfoYAML,
13
+ )
10
14
  from dstack._internal.core.errors import (
11
15
  BackendNotAvailable,
12
16
  ResourceNotExistsError,
13
17
  ServerClientError,
14
18
  )
15
- from dstack._internal.core.models.backends import AnyConfigInfoWithCreds, BackendInfoYAML
16
- from dstack._internal.core.models.backends.aws import AnyAWSCreds, AWSOSImageConfig
17
- from dstack._internal.core.models.backends.azure import AnyAzureCreds
18
19
  from dstack._internal.core.models.backends.base import BackendType
19
- from dstack._internal.core.models.backends.cudo import AnyCudoCreds
20
- from dstack._internal.core.models.backends.datacrunch import AnyDataCrunchCreds
21
- from dstack._internal.core.models.backends.kubernetes import KubernetesNetworkingConfig
22
- from dstack._internal.core.models.backends.lambdalabs import AnyLambdaCreds
23
- from dstack._internal.core.models.backends.oci import AnyOCICreds
24
- from dstack._internal.core.models.backends.runpod import AnyRunpodCreds
25
- from dstack._internal.core.models.backends.tensordock import AnyTensorDockCreds
26
- from dstack._internal.core.models.backends.vastai import AnyVastAICreds
27
- from dstack._internal.core.models.backends.vultr import AnyVultrCreds
28
20
  from dstack._internal.core.models.common import CoreModel
29
21
  from dstack._internal.server import settings
30
22
  from dstack._internal.server.models import ProjectModel, UserModel
@@ -37,7 +29,6 @@ from dstack._internal.server.services.permissions import (
37
29
  DefaultPermissions,
38
30
  set_default_permissions,
39
31
  )
40
- from dstack._internal.utils.common import run_async
41
32
  from dstack._internal.utils.logging import get_logger
42
33
 
43
34
  logger = get_logger(__name__)
@@ -58,473 +49,15 @@ def seq_representer(dumper, sequence):
58
49
  yaml.add_representer(list, seq_representer)
59
50
 
60
51
 
61
- # Below we define pydantic models for configs allowed in server/config.yml and YAML-based API.
62
- # There are some differences between the two, e.g. server/config.yml fills file-based
63
- # credentials by looking for a file, while YAML-based API doesn't do this.
64
- # So for some backends there are two sets of config models.
65
-
66
-
67
- class AWSConfig(CoreModel):
68
- type: Annotated[Literal["aws"], Field(description="The type of the backend")] = "aws"
69
- regions: Annotated[
70
- Optional[List[str]], Field(description="The list of AWS regions. Omit to use all regions")
71
- ] = None
72
- vpc_name: Annotated[
73
- Optional[str],
74
- Field(
75
- description=(
76
- "The name of custom VPCs. All configured regions must have a VPC with this name."
77
- " If your custom VPCs don't have names or have different names in different regions, use `vpc_ids` instead."
78
- )
79
- ),
80
- ] = None
81
- vpc_ids: Annotated[
82
- Optional[Dict[str, str]],
83
- Field(
84
- description=(
85
- "The mapping from AWS regions to VPC IDs."
86
- " If `default_vpcs: true`, omitted regions will use default VPCs"
87
- )
88
- ),
89
- ] = None
90
- default_vpcs: Annotated[
91
- Optional[bool],
92
- Field(
93
- description=(
94
- "A flag to enable/disable using default VPCs in regions not configured by `vpc_ids`."
95
- " Set to `false` if default VPCs should never be used."
96
- " Defaults to `true`"
97
- )
98
- ),
99
- ] = None
100
- public_ips: Annotated[
101
- Optional[bool],
102
- Field(
103
- description=(
104
- "A flag to enable/disable public IP assigning on instances."
105
- " `public_ips: false` requires at least one private subnet with outbound internet connectivity"
106
- " provided by a NAT Gateway or a Transit Gateway."
107
- " Defaults to `true`"
108
- )
109
- ),
110
- ] = None
111
- iam_instance_profile: Annotated[
112
- Optional[str],
113
- Field(
114
- description=(
115
- "The name of the IAM instance profile to associate with EC2 instances."
116
- " You can also specify the IAM role name for roles created via the AWS console."
117
- " AWS automatically creates an instance profile and gives it the same name as the role"
118
- )
119
- ),
120
- ] = None
121
- tags: Annotated[
122
- Optional[Dict[str, str]],
123
- Field(description="The tags that will be assigned to resources created by `dstack`"),
124
- ] = None
125
- os_images: Annotated[
126
- Optional[AWSOSImageConfig],
127
- Field(
128
- description="The mapping of instance categories (CPU, NVIDIA GPU) to AMI configurations"
129
- ),
130
- ] = None
131
- creds: AnyAWSCreds = Field(..., description="The credentials", discriminator="type")
132
-
133
-
134
- class AzureConfig(CoreModel):
135
- type: Annotated[Literal["azure"], Field(description="The type of the backend")] = "azure"
136
- tenant_id: Annotated[str, Field(description="The tenant ID")]
137
- subscription_id: Annotated[str, Field(description="The subscription ID")]
138
- resource_group: Annotated[
139
- Optional[str],
140
- Field(
141
- description=(
142
- "The resource group for resources created by `dstack`."
143
- " If not specified, `dstack` will create a new resource group"
144
- )
145
- ),
146
- ] = None
147
- regions: Annotated[
148
- Optional[List[str]],
149
- Field(description="The list of Azure regions (locations). Omit to use all regions"),
150
- ] = None
151
- vpc_ids: Annotated[
152
- Optional[Dict[str, str]],
153
- Field(
154
- description=(
155
- "The mapping from configured Azure locations to network IDs."
156
- " A network ID must have a format `networkResourceGroup/networkName`"
157
- " If not specified, `dstack` will create a new network for every configured region"
158
- )
159
- ),
160
- ] = None
161
- public_ips: Annotated[
162
- Optional[bool],
163
- Field(
164
- description=(
165
- "A flag to enable/disable public IP assigning on instances."
166
- " `public_ips: false` requires `vpc_ids` that specifies custom networks with outbound internet connectivity"
167
- " provided by NAT Gateway or other mechanism."
168
- " Defaults to `true`"
169
- )
170
- ),
171
- ] = None
172
- tags: Annotated[
173
- Optional[Dict[str, str]],
174
- Field(description="The tags that will be assigned to resources created by `dstack`"),
175
- ] = None
176
- creds: AnyAzureCreds = Field(..., description="The credentials", discriminator="type")
177
-
178
-
179
- class CudoConfig(CoreModel):
180
- type: Annotated[Literal["cudo"], Field(description="The type of backend")] = "cudo"
181
- regions: Annotated[
182
- Optional[List[str]], Field(description="The list of Cudo regions. Omit to use all regions")
183
- ] = None
184
- project_id: Annotated[str, Field(description="The project ID")]
185
- creds: Annotated[AnyCudoCreds, Field(description="The credentials")]
186
-
187
-
188
- class DataCrunchConfig(CoreModel):
189
- type: Annotated[Literal["datacrunch"], Field(description="The type of backend")] = "datacrunch"
190
- regions: Annotated[
191
- Optional[List[str]],
192
- Field(description="The list of DataCrunch regions. Omit to use all regions"),
193
- ] = None
194
- creds: Annotated[AnyDataCrunchCreds, Field(description="The credentials")]
195
-
196
-
197
- class GCPServiceAccountCreds(CoreModel):
198
- type: Annotated[Literal["service_account"], Field(description="The type of credentials")] = (
199
- "service_account"
200
- )
201
- filename: Annotated[str, Field(description="The path to the service account file")]
202
- data: Annotated[
203
- Optional[str],
204
- Field(
205
- description=(
206
- "The contents of the service account file."
207
- " When configuring via `server/config.yml`, it's automatically filled from `filename`."
208
- " When configuring via UI, it has to be specified explicitly"
209
- )
210
- ),
211
- ] = None
212
-
213
- @root_validator
214
- def fill_data(cls, values):
215
- return _fill_data(values)
216
-
217
-
218
- class GCPServiceAccountAPICreds(CoreModel):
219
- type: Annotated[Literal["service_account"], Field(description="The type of credentials")] = (
220
- "service_account"
221
- )
222
- filename: Annotated[
223
- Optional[str], Field(description="The path to the service account file")
224
- ] = ""
225
- data: Annotated[str, Field(description="The contents of the service account file")]
226
-
227
-
228
- class GCPDefaultCreds(CoreModel):
229
- type: Annotated[Literal["default"], Field(description="The type of credentials")] = "default"
230
-
231
-
232
- AnyGCPCreds = Union[GCPServiceAccountCreds, GCPDefaultCreds]
233
- AnyGCPAPICreds = Union[GCPServiceAccountAPICreds, GCPDefaultCreds]
234
-
235
-
236
- class GCPConfig(CoreModel):
237
- type: Annotated[Literal["gcp"], Field(description="The type of backend")] = "gcp"
238
- project_id: Annotated[str, Field(description="The project ID")]
239
- regions: Annotated[
240
- Optional[List[str]], Field(description="The list of GCP regions. Omit to use all regions")
241
- ] = None
242
- vpc_name: Annotated[Optional[str], Field(description="The name of a custom VPC")] = None
243
- vpc_project_id: Annotated[
244
- Optional[str],
245
- Field(description="The shared VPC hosted project ID. Required for shared VPC only"),
246
- ] = None
247
- public_ips: Annotated[
248
- Optional[bool],
249
- Field(
250
- description="A flag to enable/disable public IP assigning on instances. Defaults to `true`"
251
- ),
252
- ] = None
253
- nat_check: Annotated[
254
- Optional[bool],
255
- Field(
256
- description=(
257
- "A flag to enable/disable a check that Cloud NAT is configured for the VPC."
258
- " This should be set to `false` when `public_ips: false` and outbound internet connectivity"
259
- " is provided by a mechanism other than Cloud NAT such as a third-party NAT appliance."
260
- " Defaults to `true`"
261
- )
262
- ),
263
- ] = None
264
- vm_service_account: Annotated[
265
- Optional[str], Field(description="The service account to associate with provisioned VMs")
266
- ] = None
267
- tags: Annotated[
268
- Optional[Dict[str, str]],
269
- Field(
270
- description="The tags (labels) that will be assigned to resources created by `dstack`"
271
- ),
272
- ] = None
273
- creds: AnyGCPCreds = Field(..., description="The credentials", discriminator="type")
274
-
275
-
276
- class GCPAPIConfig(CoreModel):
277
- type: Annotated[Literal["gcp"], Field(description="The type of backend")] = "gcp"
278
- project_id: Annotated[str, Field(description="The project ID")]
279
- regions: Annotated[
280
- Optional[List[str]], Field(description="The list of GCP regions. Omit to use all regions")
281
- ] = None
282
- vpc_name: Annotated[Optional[str], Field(description="The name of a custom VPC")] = None
283
- vpc_project_id: Annotated[
284
- Optional[str],
285
- Field(description="The shared VPC hosted project ID. Required for shared VPC only"),
286
- ] = None
287
- public_ips: Annotated[
288
- Optional[bool],
289
- Field(
290
- description="A flag to enable/disable public IP assigning on instances. Defaults to `true`"
291
- ),
292
- ] = None
293
- nat_check: Annotated[
294
- Optional[bool],
295
- Field(
296
- description=(
297
- "A flag to enable/disable a check that Cloud NAT is configured for the VPC."
298
- " This should be set to `false` when `public_ips: false` and outbound internet connectivity"
299
- " is provided by a mechanism other than Cloud NAT such as a third-party NAT appliance."
300
- " Defaults to `true`"
301
- )
302
- ),
303
- ] = None
304
- vm_service_account: Annotated[
305
- Optional[str], Field(description="The service account associated with provisioned VMs")
306
- ] = None
307
- tags: Annotated[
308
- Optional[Dict[str, str]],
309
- Field(
310
- description="The tags (labels) that will be assigned to resources created by `dstack`"
311
- ),
312
- ] = None
313
- creds: AnyGCPAPICreds = Field(..., description="The credentials", discriminator="type")
314
-
315
-
316
- class KubeconfigConfig(CoreModel):
317
- filename: Annotated[str, Field(description="The path to the kubeconfig file")]
318
- data: Annotated[
319
- Optional[str],
320
- Field(
321
- description=(
322
- "The contents of the kubeconfig file."
323
- " When configuring via `server/config.yml`, it's automatically filled from `filename`."
324
- " When configuring via UI, it has to be specified explicitly"
325
- )
326
- ),
327
- ] = None
328
-
329
- @root_validator
330
- def fill_data(cls, values):
331
- return _fill_data(values)
332
-
333
-
334
- class KubeconfigAPIConfig(CoreModel):
335
- filename: Annotated[str, Field(description="The path to the kubeconfig file")] = ""
336
- data: Annotated[str, Field(description="The contents of the kubeconfig file")]
337
-
338
-
339
- class KubernetesConfig(CoreModel):
340
- type: Annotated[Literal["kubernetes"], Field(description="The type of backend")] = "kubernetes"
341
- kubeconfig: Annotated[KubeconfigConfig, Field(description="The kubeconfig configuration")]
342
- networking: Annotated[
343
- Optional[KubernetesNetworkingConfig], Field(description="The networking configuration")
344
- ] = None
345
-
346
-
347
- class KubernetesAPIConfig(CoreModel):
348
- type: Annotated[Literal["kubernetes"], Field(description="The type of backend")] = "kubernetes"
349
- kubeconfig: Annotated[KubeconfigAPIConfig, Field(description="The kubeconfig configuration")]
350
- networking: Annotated[
351
- Optional[KubernetesNetworkingConfig], Field(description="The networking configuration")
352
- ] = None
353
-
354
-
355
- class LambdaConfig(CoreModel):
356
- type: Annotated[Literal["lambda"], Field(description="The type of backend")] = "lambda"
357
- regions: Annotated[
358
- Optional[List[str]],
359
- Field(description="The list of Lambda regions. Omit to use all regions"),
360
- ] = None
361
- creds: Annotated[AnyLambdaCreds, Field(description="The credentials")]
362
-
363
-
364
- class NebiusServiceAccountCreds(CoreModel):
365
- type: Annotated[Literal["service_account"], Field(description="The type of credentials")] = (
366
- "service_account"
367
- )
368
- filename: Annotated[str, Field(description="The path to the service account file")]
369
- data: Annotated[
370
- Optional[str], Field(description="The contents of the service account file")
371
- ] = None
372
-
373
- @root_validator
374
- def fill_data(cls, values):
375
- return _fill_data(values)
376
-
377
-
378
- class NebiusServiceAccountAPICreds(CoreModel):
379
- type: Annotated[Literal["service_account"], Field(description="The type of credentials")] = (
380
- "service_account"
381
- )
382
- filename: Annotated[str, Field(description="The path to the service account file")]
383
- data: Annotated[str, Field(description="The contents of the service account file")]
384
-
385
-
386
- AnyNebiusCreds = NebiusServiceAccountCreds
387
- AnyNebiusAPICreds = NebiusServiceAccountAPICreds
388
-
389
-
390
- class NebiusConfig(CoreModel):
391
- type: Literal["nebius"] = "nebius"
392
- cloud_id: str
393
- folder_id: str
394
- network_id: str
395
- regions: Optional[List[str]] = None
396
- creds: AnyNebiusCreds
397
-
398
-
399
- class NebiusAPIConfig(CoreModel):
400
- type: Literal["nebius"] = "nebius"
401
- cloud_id: str
402
- folder_id: str
403
- network_id: str
404
- regions: Optional[List[str]] = None
405
- creds: AnyNebiusAPICreds
406
-
407
-
408
- class OCIConfig(CoreModel):
409
- type: Annotated[Literal["oci"], Field(description="The type of backend")] = "oci"
410
- creds: Annotated[AnyOCICreds, Field(description="The credentials", discriminator="type")]
411
- regions: Annotated[
412
- Optional[List[str]],
413
- Field(description="The list of OCI regions. Omit to use all regions"),
414
- ] = None
415
- compartment_id: Annotated[
416
- Optional[str],
417
- Field(
418
- description=(
419
- "Compartment where `dstack` will create all resources."
420
- " Omit to instruct `dstack` to create a new compartment"
421
- )
422
- ),
423
- ] = None
424
-
425
-
426
- class RunpodConfig(CoreModel):
427
- type: Literal["runpod"] = "runpod"
428
- regions: Annotated[
429
- Optional[List[str]],
430
- Field(description="The list of RunPod regions. Omit to use all regions"),
431
- ] = None
432
- community_cloud: Annotated[
433
- Optional[bool],
434
- Field(
435
- description=(
436
- "Whether Community Cloud offers can be suggested in addition to Secure Cloud."
437
- f" Defaults to `{str(RUNPOD_COMMUNITY_CLOUD_DEFAULT).lower()}`"
438
- )
439
- ),
440
- ] = None
441
- creds: Annotated[AnyRunpodCreds, Field(description="The credentials")]
442
-
443
-
444
- class TensorDockConfig(CoreModel):
445
- type: Annotated[Literal["tensordock"], Field(description="The type of backend")] = "tensordock"
446
- regions: Annotated[
447
- Optional[List[str]],
448
- Field(description="The list of TensorDock regions. Omit to use all regions"),
449
- ] = None
450
- creds: Annotated[AnyTensorDockCreds, Field(description="The credentials")]
451
-
452
-
453
- class VastAIConfig(CoreModel):
454
- type: Annotated[Literal["vastai"], Field(description="The type of backend")] = "vastai"
455
- regions: Annotated[
456
- Optional[List[str]],
457
- Field(description="The list of VastAI regions. Omit to use all regions"),
458
- ] = None
459
- creds: Annotated[AnyVastAICreds, Field(description="The credentials")]
460
-
461
-
462
- class VultrConfig(CoreModel):
463
- type: Annotated[Literal["vultr"], Field(description="The type of backend")] = "vultr"
464
- regions: Annotated[
465
- Optional[List[str]],
466
- Field(description="The list of Vultr regions. Omit to use all regions"),
467
- ] = None
468
- creds: Annotated[AnyVultrCreds, Field(description="The credentials")]
469
-
470
-
471
- class DstackConfig(CoreModel):
472
- type: Annotated[Literal["dstack"], Field(description="The type of backend")] = "dstack"
473
-
474
-
475
- AnyBackendConfig = Union[
476
- AWSConfig,
477
- AzureConfig,
478
- CudoConfig,
479
- DataCrunchConfig,
480
- GCPConfig,
481
- KubernetesConfig,
482
- LambdaConfig,
483
- NebiusConfig,
484
- OCIConfig,
485
- RunpodConfig,
486
- TensorDockConfig,
487
- VastAIConfig,
488
- VultrConfig,
489
- DstackConfig,
52
+ BackendFileConfigWithCreds = Annotated[
53
+ AnyBackendFileConfigWithCreds, Field(..., discriminator="type")
490
54
  ]
491
55
 
492
- BackendConfig = Annotated[AnyBackendConfig, Field(..., discriminator="type")]
493
-
494
-
495
- class _BackendConfig(BaseModel):
496
- __root__: BackendConfig
497
-
498
-
499
- AnyBackendAPIConfig = Union[
500
- AWSConfig,
501
- AzureConfig,
502
- CudoConfig,
503
- DataCrunchConfig,
504
- GCPAPIConfig,
505
- KubernetesAPIConfig,
506
- LambdaConfig,
507
- NebiusAPIConfig,
508
- OCIConfig,
509
- RunpodConfig,
510
- TensorDockConfig,
511
- VastAIConfig,
512
- VultrConfig,
513
- DstackConfig,
514
- ]
515
-
516
-
517
- BackendAPIConfig = Annotated[AnyBackendAPIConfig, Field(..., discriminator="type")]
518
-
519
-
520
- class _BackendAPIConfig(CoreModel):
521
- __root__: BackendAPIConfig
522
-
523
56
 
524
57
  class ProjectConfig(CoreModel):
525
58
  name: Annotated[str, Field(description="The name of the project")]
526
59
  backends: Annotated[
527
- Optional[List[BackendConfig]], Field(description="The list of backends")
60
+ Optional[List[BackendFileConfigWithCreds]], Field(description="The list of backends")
528
61
  ] = None
529
62
 
530
63
 
@@ -555,19 +88,13 @@ class ServerConfigManager:
555
88
  Initializes the default server/config.yml.
556
89
  The default config is empty or contains an existing `main` project config.
557
90
  """
558
- # The backends auto init feature via default creds is currently disabled
559
- # so that the backend configuration is always explicit.
560
- # Details: https://github.com/dstackai/dstack/issues/1384
561
- self.config = await self._init_config(session=session, init_backends=False)
91
+ self.config = await self._init_config(session)
562
92
  if self.config is not None:
563
93
  self._save_config(self.config)
564
94
 
565
95
  async def sync_config(self, session: AsyncSession):
566
96
  # Disable config.yml sync for https://github.com/dstackai/dstack/issues/815.
567
97
  return
568
- # self.config = await self._init_config(session=session, init_backends=False)
569
- # if self.config is not None:
570
- # self._save_config(self.config)
571
98
 
572
99
  async def apply_encryption(self):
573
100
  if self.config is None:
@@ -603,13 +130,15 @@ class ServerConfigManager:
603
130
  project = await projects_services.get_project_model_by_name_or_error(
604
131
  session=session, project_name=project_config.name
605
132
  )
606
- backends_to_delete = set(backends_services.list_available_backend_types())
607
- for backend_config in project_config.backends or []:
608
- config_info = config_to_internal_config(backend_config)
609
- backend_type = BackendType(config_info.type)
133
+ backends_to_delete = set(
134
+ dstack._internal.core.backends.configurators.list_available_backend_types()
135
+ )
136
+ for backend_file_config in project_config.backends or []:
137
+ backend_config = file_config_to_config(backend_file_config)
138
+ backend_type = BackendType(backend_config.type)
610
139
  backends_to_delete.difference_update([backend_type])
611
140
  try:
612
- current_config_info = await backends_services.get_config_info(
141
+ current_backend_config = await backends_services.get_backend_config(
613
142
  project=project,
614
143
  backend_type=backend_type,
615
144
  )
@@ -620,23 +149,23 @@ class ServerConfigManager:
620
149
  backend_type.value,
621
150
  )
622
151
  continue
623
- if config_info == current_config_info:
152
+ if backend_config == current_backend_config:
624
153
  continue
625
154
  backend_exists = any(backend_type == b.type for b in project.backends)
626
155
  try:
627
- # current_config_info may be None if backend exists
156
+ # current_backend_config may be None if backend exists
628
157
  # but it's config is invalid (e.g. cannot be decrypted).
629
158
  # Update backend in this case.
630
- if current_config_info is None and not backend_exists:
159
+ if current_backend_config is None and not backend_exists:
631
160
  await backends_services.create_backend(
632
- session=session, project=project, config=config_info
161
+ session=session, project=project, config=backend_config
633
162
  )
634
163
  else:
635
164
  await backends_services.update_backend(
636
- session=session, project=project, config=config_info
165
+ session=session, project=project, config=backend_config
637
166
  )
638
167
  except Exception as e:
639
- logger.warning("Failed to configure backend %s: %s", config_info.type, e)
168
+ logger.warning("Failed to configure backend %s: %s", backend_config.type, e)
640
169
  await delete_backends_safe(
641
170
  session=session,
642
171
  project=project,
@@ -644,9 +173,7 @@ class ServerConfigManager:
644
173
  error=False,
645
174
  )
646
175
 
647
- async def _init_config(
648
- self, session: AsyncSession, init_backends: bool
649
- ) -> Optional[ServerConfig]:
176
+ async def _init_config(self, session: AsyncSession) -> Optional[ServerConfig]:
650
177
  project = await projects_services.get_project_model_by_name(
651
178
  session=session,
652
179
  project_name=settings.DEFAULT_PROJECT_NAME,
@@ -656,40 +183,20 @@ class ServerConfigManager:
656
183
  # Force project reload to reflect updates when syncing
657
184
  await session.refresh(project)
658
185
  backends = []
659
- for backend_type in backends_services.list_available_backend_types():
660
- config_info = await backends_services.get_config_info(
186
+ for (
187
+ backend_type
188
+ ) in dstack._internal.core.backends.configurators.list_available_backend_types():
189
+ backend_config = await backends_services.get_backend_config(
661
190
  project=project, backend_type=backend_type
662
191
  )
663
- if config_info is not None:
664
- backends.append(internal_config_to_config(config_info))
665
- if init_backends and len(backends) == 0:
666
- backends = await self._init_backends(session=session, project=project)
192
+ if backend_config is not None:
193
+ backends.append(backend_config)
667
194
  return ServerConfig(
668
195
  projects=[ProjectConfig(name=settings.DEFAULT_PROJECT_NAME, backends=backends)],
669
196
  encryption=EncryptionConfig(keys=[]),
670
197
  default_permissions=None,
671
198
  )
672
199
 
673
- async def _init_backends(
674
- self, session: AsyncSession, project: ProjectModel
675
- ) -> List[BackendConfig]:
676
- backends = []
677
- for backend_type in backends_services.list_available_backend_types():
678
- configurator = backends_services.get_configurator(backend_type)
679
- if configurator is None:
680
- continue
681
- config_infos = await run_async(configurator.get_default_configs)
682
- for config_info in config_infos:
683
- try:
684
- await backends_services.create_backend(
685
- session=session, project=project, config=config_info
686
- )
687
- backends.append(internal_config_to_config(config_info))
688
- break
689
- except Exception as e:
690
- logger.debug("Failed to configure backend %s: %s", config_info.type, e)
691
- return backends
692
-
693
200
  def _load_config(self) -> Optional[ServerConfig]:
694
201
  try:
695
202
  with open(settings.SERVER_CONFIG_FILE_PATH) as f:
@@ -707,13 +214,12 @@ class ServerConfigManager:
707
214
  async def get_backend_config_yaml(
708
215
  project: ProjectModel, backend_type: BackendType
709
216
  ) -> BackendInfoYAML:
710
- config_info = await backends_services.get_config_info(
217
+ backend_config = await backends_services.get_backend_config(
711
218
  project=project, backend_type=backend_type
712
219
  )
713
- if config_info is None:
220
+ if backend_config is None:
714
221
  raise ResourceNotExistsError()
715
- config = internal_config_to_config(config_info)
716
- config_yaml = config_to_yaml(config)
222
+ config_yaml = config_to_yaml(backend_config)
717
223
  return BackendInfoYAML(
718
224
  name=backend_type,
719
225
  config_yaml=config_yaml,
@@ -725,9 +231,8 @@ async def create_backend_config_yaml(
725
231
  project: ProjectModel,
726
232
  config_yaml: str,
727
233
  ):
728
- backend_config = config_yaml_to_backend_config(config_yaml)
729
- config_info = config_to_internal_config(backend_config)
730
- await backends_services.create_backend(session=session, project=project, config=config_info)
234
+ config = config_yaml_to_backend_config(config_yaml)
235
+ await backends_services.create_backend(session=session, project=project, config=config)
731
236
 
732
237
 
733
238
  async def update_backend_config_yaml(
@@ -735,64 +240,35 @@ async def update_backend_config_yaml(
735
240
  project: ProjectModel,
736
241
  config_yaml: str,
737
242
  ):
738
- backend_config = config_yaml_to_backend_config(config_yaml)
739
- config_info = config_to_internal_config(backend_config)
740
- await backends_services.update_backend(session=session, project=project, config=config_info)
243
+ config = config_yaml_to_backend_config(config_yaml)
244
+ await backends_services.update_backend(session=session, project=project, config=config)
741
245
 
742
246
 
743
- server_config_manager = ServerConfigManager()
744
-
745
-
746
- def internal_config_to_config(config_info: AnyConfigInfoWithCreds) -> BackendConfig:
747
- backend_config = _BackendConfig.parse_obj(config_info.dict(exclude={"locations"}))
748
- if config_info.type == "azure":
749
- backend_config.__root__.regions = config_info.locations
750
- return backend_config.__root__
751
-
247
+ class _BackendConfigWithCreds(CoreModel):
248
+ """
249
+ Model for parsing API and file YAML configs.
250
+ """
752
251
 
753
- class _ConfigInfoWithCreds(CoreModel):
754
- __root__: Annotated[AnyConfigInfoWithCreds, Field(..., discriminator="type")]
252
+ __root__: Annotated[AnyBackendConfigWithCreds, Field(..., discriminator="type")]
755
253
 
756
254
 
757
- def config_to_internal_config(
758
- backend_config: Union[BackendConfig, BackendAPIConfig],
759
- ) -> AnyConfigInfoWithCreds:
760
- backend_config_dict = backend_config.dict()
761
- # Allow to not specify networking
762
- if backend_config.type == "kubernetes":
763
- if backend_config.networking is None:
764
- backend_config_dict["networking"] = {}
765
- if backend_config.type == "azure":
766
- backend_config_dict["locations"] = backend_config_dict["regions"]
767
- del backend_config_dict["regions"]
768
- config_info = _ConfigInfoWithCreds.parse_obj(backend_config_dict)
769
- return config_info.__root__
770
-
771
-
772
- def config_yaml_to_backend_config(config_yaml: str) -> BackendAPIConfig:
255
+ def config_yaml_to_backend_config(config_yaml: str) -> AnyBackendConfigWithCreds:
773
256
  try:
774
257
  config_dict = yaml.load(config_yaml, yaml.FullLoader)
775
258
  except yaml.YAMLError:
776
259
  raise ServerClientError("Error parsing YAML")
777
260
  try:
778
- backend_config = _BackendAPIConfig.parse_obj(config_dict).__root__
261
+ backend_config = _BackendConfigWithCreds.parse_obj(config_dict).__root__
779
262
  except ValidationError as e:
780
263
  raise ServerClientError(str(e))
781
264
  return backend_config
782
265
 
783
266
 
784
- def config_to_yaml(config: CoreModel) -> str:
785
- return yaml.dump(config.dict(exclude_none=True), sort_keys=False)
267
+ def file_config_to_config(file_config: AnyBackendFileConfigWithCreds) -> AnyBackendConfigWithCreds:
268
+ backend_config_dict = file_config.dict()
269
+ backend_config = _BackendConfigWithCreds.parse_obj(backend_config_dict)
270
+ return backend_config.__root__
786
271
 
787
272
 
788
- def _fill_data(values: dict):
789
- if values.get("data") is not None:
790
- return values
791
- if "filename" not in values:
792
- raise ValueError()
793
- try:
794
- with open(Path(values["filename"]).expanduser()) as f:
795
- values["data"] = f.read()
796
- except OSError:
797
- raise ValueError(f"No such file {values['filename']}")
798
- return values
273
+ def config_to_yaml(config: CoreModel) -> str:
274
+ return yaml.dump(config.dict(exclude_none=True), sort_keys=False)