skypilot-nightly 1.0.0.dev20250627__py3-none-any.whl → 1.0.0.dev20250630__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.
Files changed (173) hide show
  1. sky/__init__.py +2 -2
  2. sky/adaptors/kubernetes.py +14 -0
  3. sky/adaptors/nebius.py +2 -2
  4. sky/authentication.py +12 -5
  5. sky/backends/backend_utils.py +92 -26
  6. sky/check.py +5 -2
  7. sky/client/cli/command.py +39 -8
  8. sky/client/sdk.py +217 -167
  9. sky/client/service_account_auth.py +47 -0
  10. sky/clouds/aws.py +10 -4
  11. sky/clouds/azure.py +5 -2
  12. sky/clouds/cloud.py +5 -2
  13. sky/clouds/gcp.py +31 -18
  14. sky/clouds/kubernetes.py +54 -34
  15. sky/clouds/nebius.py +8 -2
  16. sky/clouds/ssh.py +5 -2
  17. sky/clouds/utils/aws_utils.py +10 -4
  18. sky/clouds/utils/gcp_utils.py +22 -7
  19. sky/clouds/utils/oci_utils.py +62 -14
  20. sky/dashboard/out/404.html +1 -1
  21. sky/dashboard/out/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js +1 -0
  22. sky/dashboard/out/_next/static/chunks/1043-1b39779691bb4030.js +1 -0
  23. sky/dashboard/out/_next/static/chunks/{141-fa5a20cbf401b351.js → 1141-726e5a3f00b67185.js} +2 -2
  24. sky/dashboard/out/_next/static/chunks/1272-1ef0bf0237faccdb.js +1 -0
  25. sky/dashboard/out/_next/static/chunks/1664-d65361e92b85e786.js +1 -0
  26. sky/dashboard/out/_next/static/chunks/1691.44e378727a41f3b5.js +21 -0
  27. sky/dashboard/out/_next/static/chunks/1871-80dea41717729fa5.js +6 -0
  28. sky/dashboard/out/_next/static/chunks/2544.27f70672535675ed.js +1 -0
  29. sky/dashboard/out/_next/static/chunks/{875.52c962183328b3f2.js → 2875.c24c6d57dc82e436.js} +1 -1
  30. sky/dashboard/out/_next/static/chunks/3256.7257acd01b481bed.js +11 -0
  31. sky/dashboard/out/_next/static/chunks/3698-52ad1ca228faa776.js +1 -0
  32. sky/dashboard/out/_next/static/chunks/3785.b3cc2bc1d49d2c3c.js +1 -0
  33. sky/dashboard/out/_next/static/chunks/3937.d7f1c55d1916c7f2.js +1 -0
  34. sky/dashboard/out/_next/static/chunks/{947-6620842ef80ae879.js → 3947-b059261d6fa88a1f.js} +1 -1
  35. sky/dashboard/out/_next/static/chunks/{697.6460bf72e760addd.js → 4697.f5421144224da9fc.js} +1 -1
  36. sky/dashboard/out/_next/static/chunks/4725.4c849b1e05c8e9ad.js +1 -0
  37. sky/dashboard/out/_next/static/chunks/5230-df791914b54d91d9.js +1 -0
  38. sky/dashboard/out/_next/static/chunks/{491.b3d264269613fe09.js → 5491.918ffed0ba7a5294.js} +1 -1
  39. sky/dashboard/out/_next/static/chunks/5739-5ea3ffa10fc884f2.js +8 -0
  40. sky/dashboard/out/_next/static/chunks/616-162f3033ffcd3d31.js +39 -0
  41. sky/dashboard/out/_next/static/chunks/6601-fcfad0ddf92ec7ab.js +1 -0
  42. sky/dashboard/out/_next/static/chunks/6989-6ff4e45dfb49d11d.js +1 -0
  43. sky/dashboard/out/_next/static/chunks/6990-d0dc765474fa0eca.js +1 -0
  44. sky/dashboard/out/_next/static/chunks/8969-909d53833da080cb.js +1 -0
  45. sky/dashboard/out/_next/static/chunks/8982.a2e214068f30a857.js +1 -0
  46. sky/dashboard/out/_next/static/chunks/{25.76c246239df93d50.js → 9025.a7c44babfe56ce09.js} +2 -2
  47. sky/dashboard/out/_next/static/chunks/938-044ad21de8b4626b.js +1 -0
  48. sky/dashboard/out/_next/static/chunks/9470-21d059a1dfa03f61.js +1 -0
  49. sky/dashboard/out/_next/static/chunks/9984.739ae958a066298d.js +1 -0
  50. sky/dashboard/out/_next/static/chunks/fd9d1056-61f2257a9cd8b32b.js +1 -0
  51. sky/dashboard/out/_next/static/chunks/{framework-87d061ee6ed71b28.js → framework-efc06c2733009cd3.js} +1 -1
  52. sky/dashboard/out/_next/static/chunks/main-app-68c028b1bc5e1b72.js +1 -0
  53. sky/dashboard/out/_next/static/chunks/{main-e0e2335212e72357.js → main-c0a4f1ea606d48d2.js} +1 -1
  54. sky/dashboard/out/_next/static/chunks/pages/{_app-9a3ce3170d2edcec.js → _app-a37b06ddb64521fd.js} +2 -2
  55. sky/dashboard/out/_next/static/chunks/pages/_error-c72a1f77a3c0be1b.js +1 -0
  56. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-8135aba0712bda37.js +6 -0
  57. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-b8e1114e6d38218c.js +6 -0
  58. sky/dashboard/out/_next/static/chunks/pages/clusters-9744c271a1642f76.js +1 -0
  59. sky/dashboard/out/_next/static/chunks/pages/config-a2673b256b6d416f.js +1 -0
  60. sky/dashboard/out/_next/static/chunks/pages/index-927ddeebe57a8ac3.js +1 -0
  61. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-8b0809f59034d509.js +1 -0
  62. sky/dashboard/out/_next/static/chunks/pages/infra-ae9d2f705ce582c9.js +1 -0
  63. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-c4d5cfac7fbc0668.js +16 -0
  64. sky/dashboard/out/_next/static/chunks/pages/jobs-5bbdc71878f0a068.js +1 -0
  65. sky/dashboard/out/_next/static/chunks/pages/users-cd43fb3c122eedde.js +1 -0
  66. sky/dashboard/out/_next/static/chunks/pages/volumes-4ebf6484f7216387.js +1 -0
  67. sky/dashboard/out/_next/static/chunks/pages/workspace/new-5629d4e551dba1ee.js +1 -0
  68. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-7c0187f43757a548.js +1 -0
  69. sky/dashboard/out/_next/static/chunks/pages/workspaces-06bde99155fa6292.js +1 -0
  70. sky/dashboard/out/_next/static/chunks/webpack-d427db53e54de9ce.js +1 -0
  71. sky/dashboard/out/_next/static/css/0da6afe66176678a.css +3 -0
  72. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  73. sky/dashboard/out/clusters/[cluster].html +1 -1
  74. sky/dashboard/out/clusters.html +1 -1
  75. sky/dashboard/out/config.html +1 -1
  76. sky/dashboard/out/index.html +1 -1
  77. sky/dashboard/out/infra/[context].html +1 -1
  78. sky/dashboard/out/infra.html +1 -1
  79. sky/dashboard/out/jobs/[job].html +1 -1
  80. sky/dashboard/out/jobs.html +1 -1
  81. sky/dashboard/out/users.html +1 -1
  82. sky/dashboard/out/volumes.html +1 -1
  83. sky/dashboard/out/workspace/new.html +1 -1
  84. sky/dashboard/out/workspaces/[name].html +1 -1
  85. sky/dashboard/out/workspaces.html +1 -1
  86. sky/data/storage.py +8 -3
  87. sky/global_user_state.py +257 -9
  88. sky/jobs/client/sdk.py +20 -25
  89. sky/models.py +16 -0
  90. sky/optimizer.py +46 -0
  91. sky/provision/__init__.py +14 -6
  92. sky/provision/kubernetes/config.py +1 -1
  93. sky/provision/kubernetes/constants.py +9 -0
  94. sky/provision/kubernetes/instance.py +24 -18
  95. sky/provision/kubernetes/network.py +15 -9
  96. sky/provision/kubernetes/network_utils.py +42 -23
  97. sky/provision/kubernetes/utils.py +73 -35
  98. sky/provision/kubernetes/volume.py +77 -15
  99. sky/provision/nebius/utils.py +10 -4
  100. sky/resources.py +10 -4
  101. sky/serve/client/sdk.py +28 -34
  102. sky/server/common.py +51 -3
  103. sky/server/constants.py +3 -0
  104. sky/server/requests/executor.py +4 -0
  105. sky/server/requests/payloads.py +33 -0
  106. sky/server/requests/requests.py +19 -0
  107. sky/server/rest.py +6 -15
  108. sky/server/server.py +121 -6
  109. sky/skylet/constants.py +7 -0
  110. sky/skypilot_config.py +32 -4
  111. sky/task.py +12 -0
  112. sky/users/permission.py +29 -0
  113. sky/users/server.py +384 -5
  114. sky/users/token_service.py +196 -0
  115. sky/utils/common_utils.py +4 -5
  116. sky/utils/config_utils.py +41 -0
  117. sky/utils/controller_utils.py +5 -1
  118. sky/utils/log_utils.py +68 -0
  119. sky/utils/resource_checker.py +153 -0
  120. sky/utils/resources_utils.py +12 -4
  121. sky/utils/schemas.py +87 -60
  122. sky/utils/subprocess_utils.py +2 -6
  123. sky/volumes/server/core.py +103 -78
  124. sky/volumes/utils.py +22 -5
  125. sky/workspaces/core.py +9 -117
  126. {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/METADATA +1 -1
  127. {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/RECORD +133 -128
  128. sky/dashboard/out/_next/static/HudU4f4Xsy-cP51JvXSZ-/_buildManifest.js +0 -1
  129. sky/dashboard/out/_next/static/chunks/230-d6e363362017ff3a.js +0 -1
  130. sky/dashboard/out/_next/static/chunks/43-36177d00f6956ab2.js +0 -1
  131. sky/dashboard/out/_next/static/chunks/470-92dd1614396389be.js +0 -1
  132. sky/dashboard/out/_next/static/chunks/544.110e53813fb98e2e.js +0 -1
  133. sky/dashboard/out/_next/static/chunks/616-d6128fa9e7cae6e6.js +0 -39
  134. sky/dashboard/out/_next/static/chunks/645.961f08e39b8ce447.js +0 -1
  135. sky/dashboard/out/_next/static/chunks/664-047bc03493fda379.js +0 -1
  136. sky/dashboard/out/_next/static/chunks/690.55f9eed3be903f56.js +0 -16
  137. sky/dashboard/out/_next/static/chunks/785.dc2686c3c1235554.js +0 -1
  138. sky/dashboard/out/_next/static/chunks/798-c0525dc3f21e488d.js +0 -1
  139. sky/dashboard/out/_next/static/chunks/799-3625946b2ec2eb30.js +0 -8
  140. sky/dashboard/out/_next/static/chunks/871-3db673be3ee3750b.js +0 -6
  141. sky/dashboard/out/_next/static/chunks/937.3759f538f11a0953.js +0 -1
  142. sky/dashboard/out/_next/static/chunks/938-068520cc11738deb.js +0 -1
  143. sky/dashboard/out/_next/static/chunks/969-d3a0b53f728d280a.js +0 -1
  144. sky/dashboard/out/_next/static/chunks/973-81b2d057178adb76.js +0 -1
  145. sky/dashboard/out/_next/static/chunks/982.1b61658204416b0f.js +0 -1
  146. sky/dashboard/out/_next/static/chunks/984.e8bac186a24e5178.js +0 -1
  147. sky/dashboard/out/_next/static/chunks/989-db34c16ad7ea6155.js +0 -1
  148. sky/dashboard/out/_next/static/chunks/990-0ad5ea1699e03ee8.js +0 -1
  149. sky/dashboard/out/_next/static/chunks/fd9d1056-2821b0f0cabcd8bd.js +0 -1
  150. sky/dashboard/out/_next/static/chunks/main-app-241eb28595532291.js +0 -1
  151. sky/dashboard/out/_next/static/chunks/pages/_error-1be831200e60c5c0.js +0 -1
  152. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-aff040d7bc5d0086.js +0 -6
  153. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-8040f2483897ed0c.js +0 -6
  154. sky/dashboard/out/_next/static/chunks/pages/clusters-f119a5630a1efd61.js +0 -1
  155. sky/dashboard/out/_next/static/chunks/pages/config-6b255eae088da6a3.js +0 -1
  156. sky/dashboard/out/_next/static/chunks/pages/index-6b0d9e5031b70c58.js +0 -1
  157. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-b302aea4d65766bf.js +0 -1
  158. sky/dashboard/out/_next/static/chunks/pages/infra-ee8cc4d449945d19.js +0 -1
  159. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-e4b23128db0774cd.js +0 -16
  160. sky/dashboard/out/_next/static/chunks/pages/jobs-0a5695ff3075d94a.js +0 -1
  161. sky/dashboard/out/_next/static/chunks/pages/users-4978cbb093e141e7.js +0 -1
  162. sky/dashboard/out/_next/static/chunks/pages/volumes-476b670ef33d1ecd.js +0 -1
  163. sky/dashboard/out/_next/static/chunks/pages/workspace/new-5b59bce9eb208d84.js +0 -1
  164. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-cb7e720b739de53a.js +0 -1
  165. sky/dashboard/out/_next/static/chunks/pages/workspaces-50e230828730cfb3.js +0 -1
  166. sky/dashboard/out/_next/static/chunks/webpack-08fdb9e6070127fc.js +0 -1
  167. sky/dashboard/out/_next/static/css/52082cf558ec9705.css +0 -3
  168. /sky/dashboard/out/_next/static/{HudU4f4Xsy-cP51JvXSZ- → NdypbqMxaYucRGfopkKXa}/_ssgManifest.js +0 -0
  169. /sky/dashboard/out/_next/static/chunks/{804-4c9fc53aa74bc191.js → 804-9f5e98ce84d46bdd.js} +0 -0
  170. {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/WHEEL +0 -0
  171. {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/entry_points.txt +0 -0
  172. {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/licenses/LICENSE +0 -0
  173. {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/top_level.txt +0 -0
sky/provision/__init__.py CHANGED
@@ -6,7 +6,7 @@ providers supported by SkyPilot need to follow.
6
6
  import functools
7
7
  import inspect
8
8
  import typing
9
- from typing import Any, Dict, List, Optional, Type
9
+ from typing import Any, Dict, List, Optional, Tuple, Type
10
10
 
11
11
  from sky import models
12
12
  from sky import sky_logging
@@ -106,7 +106,7 @@ def bootstrap_instances(
106
106
 
107
107
  @_route_to_cloud_impl
108
108
  def apply_volume(provider_name: str,
109
- config: models.VolumeConfig) -> models.VolumeConfig:
109
+ volume_config: models.VolumeConfig) -> models.VolumeConfig:
110
110
  """Create or register a volume.
111
111
 
112
112
  This function creates or registers a volume with the provided configuration,
@@ -117,15 +117,23 @@ def apply_volume(provider_name: str,
117
117
 
118
118
  @_route_to_cloud_impl
119
119
  def delete_volume(provider_name: str,
120
- config: models.VolumeConfig) -> models.VolumeConfig:
120
+ volume_config: models.VolumeConfig) -> models.VolumeConfig:
121
121
  """Delete a volume."""
122
122
  raise NotImplementedError
123
123
 
124
124
 
125
125
  @_route_to_cloud_impl
126
- def get_volume_usedby(provider_name: str,
127
- config: models.VolumeConfig) -> List[str]:
128
- """Get the usedby of a volume."""
126
+ def get_volume_usedby(
127
+ provider_name: str,
128
+ volume_config: models.VolumeConfig,
129
+ ) -> Tuple[List[str], List[str]]:
130
+ """Get the usedby of a volume.
131
+
132
+ Returns:
133
+ usedby_pods: List of pods using the volume. These may include pods
134
+ not created by SkyPilot.
135
+ usedby_clusters: List of clusters using the volume.
136
+ """
129
137
  raise NotImplementedError
130
138
 
131
139
 
@@ -35,7 +35,7 @@ def bootstrap_instances(
35
35
  _configure_services(namespace, context, config.provider_config)
36
36
 
37
37
  networking_mode = network_utils.get_networking_mode(
38
- config.provider_config.get('networking_mode'))
38
+ config.provider_config.get('networking_mode'), context)
39
39
  if networking_mode == kubernetes_enums.KubernetesNetworkingMode.NODEPORT:
40
40
  config = _configure_ssh_jump(namespace, context, config)
41
41
 
@@ -15,3 +15,12 @@ SKY_K8S_EXEC_AUTH_PATH = '$HOME/skypilot-runtime/bin:$HOME/google-cloud-sdk/bin:
15
15
 
16
16
  # cache directory for kubeconfig with modified exec auth
17
17
  SKY_K8S_EXEC_AUTH_KUBECONFIG_CACHE = '~/.sky/generated/kubeconfigs'
18
+
19
+ # Labels for the Pods created by SkyPilot
20
+ TAG_RAY_CLUSTER_NAME = 'ray-cluster-name'
21
+ TAG_SKYPILOT_CLUSTER_NAME = 'skypilot-cluster-name'
22
+ TAG_POD_INITIALIZED = 'skypilot-initialized'
23
+ TAG_SKYPILOT_DEPLOYMENT_NAME = 'skypilot-deployment-name'
24
+
25
+ # Pod phases that are not holding PVCs
26
+ PVC_NOT_HOLD_POD_PHASES = ['Succeeded', 'Failed']
@@ -12,6 +12,7 @@ from sky.provision import common
12
12
  from sky.provision import constants
13
13
  from sky.provision import docker_utils
14
14
  from sky.provision.kubernetes import config as config_lib
15
+ from sky.provision.kubernetes import constants as k8s_constants
15
16
  from sky.provision.kubernetes import network_utils
16
17
  from sky.provision.kubernetes import utils as kubernetes_utils
17
18
  from sky.provision.kubernetes import volume
@@ -30,14 +31,10 @@ _MAX_RETRIES = 3
30
31
  _NUM_THREADS = subprocess_utils.get_parallel_threads('kubernetes')
31
32
 
32
33
  logger = sky_logging.init_logger(__name__)
33
- TAG_RAY_CLUSTER_NAME = 'ray-cluster-name'
34
- TAG_SKYPILOT_CLUSTER_NAME = 'skypilot-cluster-name'
35
- TAG_POD_INITIALIZED = 'skypilot-initialized'
36
- TAG_SKYPILOT_DEPLOYMENT_NAME = 'skypilot-deployment-name'
37
34
 
38
35
 
39
36
  def ray_tag_filter(cluster_name: str) -> Dict[str, str]:
40
- return {TAG_RAY_CLUSTER_NAME: cluster_name}
37
+ return {k8s_constants.TAG_RAY_CLUSTER_NAME: cluster_name}
41
38
 
42
39
 
43
40
  def _is_head(pod) -> bool:
@@ -75,7 +72,8 @@ def is_high_availability_cluster_by_kubectl(
75
72
  deployment_list = kubernetes.apps_api(
76
73
  context).list_namespaced_deployment(
77
74
  namespace,
78
- label_selector=f'{TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}')
75
+ label_selector=
76
+ f'{k8s_constants.TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}')
79
77
  except kubernetes.api_exception():
80
78
  return False
81
79
  # It is a high availability cluster if there is at least one deployment
@@ -280,10 +278,12 @@ def _wait_for_pods_to_schedule(namespace, context, new_nodes, timeout: int):
280
278
  while _evaluate_timeout():
281
279
  # Get all pods in a single API call using the cluster name label
282
280
  # which all pods in new_nodes should share
283
- cluster_name = new_nodes[0].metadata.labels[TAG_SKYPILOT_CLUSTER_NAME]
281
+ cluster_name = new_nodes[0].metadata.labels[
282
+ k8s_constants.TAG_SKYPILOT_CLUSTER_NAME]
284
283
  pods = kubernetes.core_api(context).list_namespaced_pod(
285
284
  namespace,
286
- label_selector=f'{TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
285
+ label_selector=
286
+ f'{k8s_constants.TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
287
287
 
288
288
  # Get the set of found pod names and check if we have all expected pods
289
289
  found_pod_names = {pod.metadata.name for pod in pods}
@@ -361,10 +361,12 @@ def _wait_for_pods_to_run(namespace, context, new_nodes):
361
361
 
362
362
  while True:
363
363
  # Get all pods in a single API call
364
- cluster_name = new_nodes[0].metadata.labels[TAG_SKYPILOT_CLUSTER_NAME]
364
+ cluster_name = new_nodes[0].metadata.labels[
365
+ k8s_constants.TAG_SKYPILOT_CLUSTER_NAME]
365
366
  all_pods = kubernetes.core_api(context).list_namespaced_pod(
366
367
  namespace,
367
- label_selector=f'{TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
368
+ label_selector=
369
+ f'{k8s_constants.TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
368
370
 
369
371
  # Get the set of found pod names and check if we have all expected pods
370
372
  found_pod_names = {pod.metadata.name for pod in all_pods}
@@ -732,7 +734,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
732
734
  else:
733
735
  pod_spec['metadata']['labels'] = tags
734
736
  pod_spec['metadata']['labels'].update(
735
- {TAG_SKYPILOT_CLUSTER_NAME: cluster_name_on_cloud})
737
+ {k8s_constants.TAG_SKYPILOT_CLUSTER_NAME: cluster_name_on_cloud})
736
738
 
737
739
  terminating_pods = kubernetes_utils.filter_pods(namespace, context, tags,
738
740
  ['Terminating'])
@@ -841,7 +843,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
841
843
  'podAffinityTerm': {
842
844
  'labelSelector': {
843
845
  'matchExpressions': [{
844
- 'key': TAG_SKYPILOT_CLUSTER_NAME,
846
+ 'key': k8s_constants.TAG_SKYPILOT_CLUSTER_NAME,
845
847
  'operator': 'In',
846
848
  'values': [cluster_name_on_cloud]
847
849
  }]
@@ -884,7 +886,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
884
886
  # Add the deployment name as a label to the pod spec
885
887
  deployment_name = deployment_spec['metadata']['name']
886
888
  pod_spec_copy['metadata']['labels'][
887
- TAG_SKYPILOT_DEPLOYMENT_NAME] = deployment_name
889
+ k8s_constants.TAG_SKYPILOT_DEPLOYMENT_NAME] = deployment_name
888
890
  template_pod_spec['metadata'] = pod_spec_copy['metadata']
889
891
  template_pod_spec['spec'].update(pod_spec_copy['spec'])
890
892
  # Propagate the labels to the deployment for identification.
@@ -941,7 +943,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
941
943
  head_pod_name = pod.metadata.name
942
944
 
943
945
  networking_mode = network_utils.get_networking_mode(
944
- config.provider_config.get('networking_mode'))
946
+ config.provider_config.get('networking_mode'), context)
945
947
  if networking_mode == kubernetes_enums.KubernetesNetworkingMode.NODEPORT:
946
948
  # Adding the jump pod to the new_nodes list as well so it can be
947
949
  # checked if it's scheduled and running along with other pods.
@@ -1102,7 +1104,7 @@ def terminate_instances(
1102
1104
 
1103
1105
  # Clean up the SSH jump pod if in use
1104
1106
  networking_mode = network_utils.get_networking_mode(
1105
- provider_config.get('networking_mode'))
1107
+ provider_config.get('networking_mode'), context)
1106
1108
  if networking_mode == kubernetes_enums.KubernetesNetworkingMode.NODEPORT:
1107
1109
  pod_name = list(pods.keys())[0]
1108
1110
  try:
@@ -1147,8 +1149,11 @@ def get_cluster_info(
1147
1149
  head_pod_name = None
1148
1150
 
1149
1151
  port_forward_mode = kubernetes_enums.KubernetesNetworkingMode.PORTFORWARD
1150
- network_mode_str = skypilot_config.get_nested(('kubernetes', 'networking'),
1151
- port_forward_mode.value)
1152
+ network_mode_str = skypilot_config.get_effective_region_config(
1153
+ cloud='kubernetes',
1154
+ region=context,
1155
+ keys=('networking_mode',),
1156
+ default_value=port_forward_mode.value)
1152
1157
  network_mode = kubernetes_enums.KubernetesNetworkingMode.from_str(
1153
1158
  network_mode_str)
1154
1159
  external_ip = kubernetes_utils.get_external_ip(network_mode, context)
@@ -1286,7 +1291,8 @@ def get_command_runners(
1286
1291
 
1287
1292
  # Try to get deployment name from label first
1288
1293
  head_instance_info = instances[pod_name][0]
1289
- deployment = head_instance_info.tags.get(TAG_SKYPILOT_DEPLOYMENT_NAME)
1294
+ deployment = head_instance_info.tags.get(
1295
+ k8s_constants.TAG_SKYPILOT_DEPLOYMENT_NAME)
1290
1296
 
1291
1297
  node_list = [((namespace, context), pod_name)]
1292
1298
  head_runner = command_runner.KubernetesCommandRunner(
@@ -22,8 +22,9 @@ def open_ports(
22
22
  ) -> None:
23
23
  """See sky/provision/__init__.py"""
24
24
  assert provider_config is not None, 'provider_config is required'
25
+ context = kubernetes_utils.get_context_from_config(provider_config)
25
26
  port_mode = network_utils.get_port_mode(
26
- provider_config.get('port_mode', None))
27
+ provider_config.get('port_mode', None), context)
27
28
  ports = list(port_ranges_to_set(ports))
28
29
  if port_mode == kubernetes_enums.KubernetesPortMode.LOADBALANCER:
29
30
  _open_ports_using_loadbalancer(
@@ -46,8 +47,10 @@ def _open_ports_using_loadbalancer(
46
47
  ) -> None:
47
48
  service_name = _LOADBALANCER_SERVICE_NAME.format(
48
49
  cluster_name_on_cloud=cluster_name_on_cloud)
50
+ context = kubernetes_utils.get_context_from_config(provider_config)
49
51
  content = network_utils.fill_loadbalancer_template(
50
52
  namespace=provider_config.get('namespace', 'default'),
53
+ context=context,
51
54
  service_name=service_name,
52
55
  ports=ports,
53
56
  selector_key='skypilot-cluster',
@@ -59,7 +62,7 @@ def _open_ports_using_loadbalancer(
59
62
 
60
63
  network_utils.create_or_replace_namespaced_service(
61
64
  namespace=kubernetes_utils.get_namespace_from_config(provider_config),
62
- context=kubernetes_utils.get_context_from_config(provider_config),
65
+ context=context,
63
66
  service_name=service_name,
64
67
  service_spec=content['service_spec'])
65
68
 
@@ -70,6 +73,7 @@ def _open_ports_using_ingress(
70
73
  provider_config: Dict[str, Any],
71
74
  ) -> None:
72
75
  context = kubernetes_utils.get_context_from_config(provider_config)
76
+ namespace = kubernetes_utils.get_namespace_from_config(provider_config)
73
77
  # Check if an ingress controller exists
74
78
  if not network_utils.ingress_controller_exists(context):
75
79
  raise Exception(
@@ -100,6 +104,7 @@ def _open_ports_using_ingress(
100
104
  # multiple rules.
101
105
  content = network_utils.fill_ingress_template(
102
106
  namespace=provider_config.get('namespace', 'default'),
107
+ context=context,
103
108
  service_details=service_details,
104
109
  ingress_name=f'{cluster_name_on_cloud}-skypilot-ingress',
105
110
  selector_key='skypilot-cluster',
@@ -111,9 +116,8 @@ def _open_ports_using_ingress(
111
116
  # Update metadata from config
112
117
  kubernetes_utils.merge_custom_metadata(service_spec['metadata'])
113
118
  network_utils.create_or_replace_namespaced_service(
114
- namespace=kubernetes_utils.get_namespace_from_config(
115
- provider_config),
116
- context=kubernetes_utils.get_context_from_config(provider_config),
119
+ namespace=namespace,
120
+ context=context,
117
121
  service_name=service_name,
118
122
  service_spec=service_spec,
119
123
  )
@@ -121,8 +125,8 @@ def _open_ports_using_ingress(
121
125
  kubernetes_utils.merge_custom_metadata(content['ingress_spec']['metadata'])
122
126
  # Create or update the single ingress for all services
123
127
  network_utils.create_or_replace_namespaced_ingress(
124
- namespace=kubernetes_utils.get_namespace_from_config(provider_config),
125
- context=kubernetes_utils.get_context_from_config(provider_config),
128
+ namespace=namespace,
129
+ context=context,
126
130
  ingress_name=f'{cluster_name_on_cloud}-skypilot-ingress',
127
131
  ingress_spec=content['ingress_spec'],
128
132
  )
@@ -135,8 +139,9 @@ def cleanup_ports(
135
139
  ) -> None:
136
140
  """See sky/provision/__init__.py"""
137
141
  assert provider_config is not None, 'provider_config is required'
142
+ context = kubernetes_utils.get_context_from_config(provider_config)
138
143
  port_mode = network_utils.get_port_mode(
139
- provider_config.get('port_mode', None))
144
+ provider_config.get('port_mode', None), context)
140
145
  ports = list(port_ranges_to_set(ports))
141
146
  if port_mode == kubernetes_enums.KubernetesPortMode.LOADBALANCER:
142
147
  _cleanup_ports_for_loadbalancer(
@@ -202,8 +207,9 @@ def query_ports(
202
207
  """See sky/provision/__init__.py"""
203
208
  del head_ip # unused
204
209
  assert provider_config is not None, 'provider_config is required'
210
+ context = kubernetes_utils.get_context_from_config(provider_config)
205
211
  port_mode = network_utils.get_port_mode(
206
- provider_config.get('port_mode', None))
212
+ provider_config.get('port_mode', None), context)
207
213
  ports = list(port_ranges_to_set(ports))
208
214
 
209
215
  try:
@@ -28,7 +28,8 @@ _LOADBALANCER_TEMPLATE_NAME = 'kubernetes-loadbalancer.yml.j2'
28
28
 
29
29
 
30
30
  def get_port_mode(
31
- mode_str: Optional[str] = None) -> kubernetes_enums.KubernetesPortMode:
31
+ mode_str: Optional[str],
32
+ context: Optional[str]) -> kubernetes_enums.KubernetesPortMode:
32
33
  """Get the port mode from the provider config."""
33
34
 
34
35
  curr_kube_config = kubernetes_utils.get_current_kube_config_context_name()
@@ -38,9 +39,11 @@ def get_port_mode(
38
39
  # If running in kind (`sky local up`), use ingress mode
39
40
  return kubernetes_enums.KubernetesPortMode.INGRESS
40
41
 
41
- mode_str = mode_str or skypilot_config.get_nested(
42
- ('kubernetes', 'ports'),
43
- kubernetes_enums.KubernetesPortMode.LOADBALANCER.value)
42
+ mode_str = mode_str or skypilot_config.get_effective_region_config(
43
+ cloud='kubernetes',
44
+ region=context,
45
+ keys=('ports',),
46
+ default_value=kubernetes_enums.KubernetesPortMode.LOADBALANCER.value)
44
47
  try:
45
48
  port_mode = kubernetes_enums.KubernetesPortMode(mode_str)
46
49
  except ValueError as e:
@@ -54,12 +57,16 @@ def get_port_mode(
54
57
 
55
58
 
56
59
  def get_networking_mode(
57
- mode_str: Optional[str] = None
60
+ mode_str: Optional[str],
61
+ context: Optional[str],
58
62
  ) -> kubernetes_enums.KubernetesNetworkingMode:
59
63
  """Get the networking mode from the provider config."""
60
- mode_str = mode_str or skypilot_config.get_nested(
61
- ('kubernetes', 'networking_mode'),
62
- kubernetes_enums.KubernetesNetworkingMode.PORTFORWARD.value)
64
+ mode_str = mode_str or skypilot_config.get_effective_region_config(
65
+ cloud='kubernetes',
66
+ region=context,
67
+ keys=('networking_mode',),
68
+ default_value=kubernetes_enums.KubernetesNetworkingMode.PORTFORWARD.
69
+ value)
63
70
  try:
64
71
  networking_mode = kubernetes_enums.KubernetesNetworkingMode.from_str(
65
72
  mode_str)
@@ -70,9 +77,9 @@ def get_networking_mode(
70
77
  return networking_mode
71
78
 
72
79
 
73
- def fill_loadbalancer_template(namespace: str, service_name: str,
74
- ports: List[int], selector_key: str,
75
- selector_value: str) -> Dict:
80
+ def fill_loadbalancer_template(namespace: str, context: Optional[str],
81
+ service_name: str, ports: List[int],
82
+ selector_key: str, selector_value: str) -> Dict:
76
83
  template_path = os.path.join(sky.__root_dir__, 'templates',
77
84
  _LOADBALANCER_TEMPLATE_NAME)
78
85
  if not os.path.exists(template_path):
@@ -81,10 +88,16 @@ def fill_loadbalancer_template(namespace: str, service_name: str,
81
88
 
82
89
  with open(template_path, 'r', encoding='utf-8') as fin:
83
90
  template = fin.read()
84
- annotations = skypilot_config.get_nested(
85
- ('kubernetes', 'custom_metadata', 'annotations'), {})
86
- labels = skypilot_config.get_nested(
87
- ('kubernetes', 'custom_metadata', 'labels'), {})
91
+ annotations = skypilot_config.get_effective_region_config(
92
+ cloud='kubernetes',
93
+ region=context,
94
+ keys=('custom_metadata', 'annotations'),
95
+ default_value={})
96
+ labels = skypilot_config.get_effective_region_config(
97
+ cloud='kubernetes',
98
+ region=context,
99
+ keys=('custom_metadata', 'labels'),
100
+ default_value={})
88
101
  j2_template = jinja2.Template(template)
89
102
  cont = j2_template.render(
90
103
  namespace=namespace,
@@ -99,10 +112,10 @@ def fill_loadbalancer_template(namespace: str, service_name: str,
99
112
  return content
100
113
 
101
114
 
102
- def fill_ingress_template(namespace: str, service_details: List[Tuple[str, int,
103
- str]],
104
- ingress_name: str, selector_key: str,
105
- selector_value: str) -> Dict:
115
+ def fill_ingress_template(namespace: str, context: Optional[str],
116
+ service_details: List[Tuple[str, int,
117
+ str]], ingress_name: str,
118
+ selector_key: str, selector_value: str) -> Dict:
106
119
  template_path = os.path.join(sky.__root_dir__, 'templates',
107
120
  _INGRESS_TEMPLATE_NAME)
108
121
  if not os.path.exists(template_path):
@@ -110,10 +123,16 @@ def fill_ingress_template(namespace: str, service_details: List[Tuple[str, int,
110
123
  f'Template "{_INGRESS_TEMPLATE_NAME}" does not exist.')
111
124
  with open(template_path, 'r', encoding='utf-8') as fin:
112
125
  template = fin.read()
113
- annotations = skypilot_config.get_nested(
114
- ('kubernetes', 'custom_metadata', 'annotations'), {})
115
- labels = skypilot_config.get_nested(
116
- ('kubernetes', 'custom_metadata', 'labels'), {})
126
+ annotations = skypilot_config.get_effective_region_config(
127
+ cloud='kubernetes',
128
+ region=context,
129
+ keys=('custom_metadata', 'annotations'),
130
+ default_value={})
131
+ labels = skypilot_config.get_effective_region_config(
132
+ cloud='kubernetes',
133
+ region=context,
134
+ keys=('custom_metadata', 'labels'),
135
+ default_value={})
117
136
  j2_template = jinja2.Template(template)
118
137
  cont = j2_template.render(
119
138
  namespace=namespace,
@@ -1190,7 +1190,11 @@ def get_accelerator_label_key_values(
1190
1190
  context_display_name = common_utils.removeprefix(
1191
1191
  context, 'ssh-') if (context and is_ssh_node_pool) else context
1192
1192
 
1193
- autoscaler_type = get_autoscaler_type()
1193
+ autoscaler_type = skypilot_config.get_effective_region_config(
1194
+ cloud='kubernetes',
1195
+ region=context,
1196
+ keys=('autoscaler',),
1197
+ default_value=None)
1194
1198
  if autoscaler_type is not None:
1195
1199
  # If autoscaler is set in config.yaml, override the label key and value
1196
1200
  # to the autoscaler's format and bypass the GPU checks.
@@ -1595,9 +1599,11 @@ def is_kubeconfig_exec_auth(
1595
1599
  user_details = next(
1596
1600
  user for user in user_details if user['name'] == target_username)
1597
1601
 
1598
- remote_identity = skypilot_config.get_nested(
1599
- ('kubernetes', 'remote_identity'),
1600
- schemas.get_default_remote_identity('kubernetes'))
1602
+ remote_identity = skypilot_config.get_effective_region_config(
1603
+ cloud='kubernetes',
1604
+ region=context,
1605
+ keys=('remote_identity',),
1606
+ default_value=schemas.get_default_remote_identity('kubernetes'))
1601
1607
  if ('exec' in user_details.get('user', {}) and remote_identity
1602
1608
  == schemas.RemoteIdentityOptions.LOCAL_CREDENTIALS.value):
1603
1609
  ctx_name = context_obj['name']
@@ -2078,7 +2084,7 @@ def setup_ssh_jump_svc(ssh_jump_name: str, namespace: str,
2078
2084
  content = fill_ssh_jump_template('', '', ssh_jump_name, service_type.value)
2079
2085
 
2080
2086
  # Add custom metadata from config
2081
- merge_custom_metadata(content['service_spec']['metadata'])
2087
+ merge_custom_metadata(content['service_spec']['metadata'], context)
2082
2088
 
2083
2089
  # Create service
2084
2090
  try:
@@ -2158,7 +2164,7 @@ def setup_ssh_jump_pod(ssh_jump_name: str, ssh_jump_image: str,
2158
2164
 
2159
2165
  # Add custom metadata to all objects
2160
2166
  for object_type in content.keys():
2161
- merge_custom_metadata(content[object_type]['metadata'])
2167
+ merge_custom_metadata(content[object_type]['metadata'], context)
2162
2168
 
2163
2169
  # ServiceAccount
2164
2170
  try:
@@ -2370,7 +2376,7 @@ def check_port_forward_mode_dependencies(
2370
2376
  return None
2371
2377
 
2372
2378
 
2373
- def get_endpoint_debug_message() -> str:
2379
+ def get_endpoint_debug_message(context: Optional[str] = None) -> str:
2374
2380
  """ Returns a string message for user to debug Kubernetes port opening
2375
2381
 
2376
2382
  Polls the configured ports mode on Kubernetes to produce an
@@ -2378,7 +2384,7 @@ def get_endpoint_debug_message() -> str:
2378
2384
 
2379
2385
  Also checks if the
2380
2386
  """
2381
- port_mode = network_utils.get_port_mode()
2387
+ port_mode = network_utils.get_port_mode(None, context)
2382
2388
  if port_mode == kubernetes_enums.KubernetesPortMode.INGRESS:
2383
2389
  endpoint_type = 'Ingress'
2384
2390
  debug_cmd = 'kubectl describe ingress && kubectl describe ingressclass'
@@ -2396,6 +2402,7 @@ def combine_pod_config_fields(
2396
2402
  cluster_yaml_path: str,
2397
2403
  cluster_config_overrides: Dict[str, Any],
2398
2404
  cloud: Optional[clouds.Cloud] = None,
2405
+ context: Optional[str] = None,
2399
2406
  ) -> None:
2400
2407
  """Adds or updates fields in the YAML with fields from the
2401
2408
  ~/.sky/config.yaml's kubernetes.pod_spec dict.
@@ -2438,19 +2445,28 @@ def combine_pod_config_fields(
2438
2445
  with open(cluster_yaml_path, 'r', encoding='utf-8') as f:
2439
2446
  yaml_content = f.read()
2440
2447
  yaml_obj = yaml.safe_load(yaml_content)
2441
- # We don't use override_configs in `skypilot_config.get_nested`, as merging
2448
+ # We don't use override_configs in `get_effective_region_config`, as merging
2442
2449
  # the pod config requires special handling.
2443
2450
  if isinstance(cloud, clouds.SSH):
2444
- kubernetes_config = skypilot_config.get_nested(('ssh', 'pod_config'),
2445
- default_value={},
2446
- override_configs={})
2447
- override_pod_config = (cluster_config_overrides.get('ssh', {}).get(
2448
- 'pod_config', {}))
2451
+ kubernetes_config = skypilot_config.get_effective_region_config(
2452
+ cloud='ssh', region=None, keys=('pod_config',), default_value={})
2453
+ override_pod_config = config_utils.get_cloud_config_value_from_dict(
2454
+ dict_config=cluster_config_overrides,
2455
+ cloud='ssh',
2456
+ keys=('pod_config',),
2457
+ default_value={})
2449
2458
  else:
2450
- kubernetes_config = skypilot_config.get_nested(
2451
- ('kubernetes', 'pod_config'), default_value={}, override_configs={})
2452
- override_pod_config = (cluster_config_overrides.get(
2453
- 'kubernetes', {}).get('pod_config', {}))
2459
+ kubernetes_config = skypilot_config.get_effective_region_config(
2460
+ cloud='kubernetes',
2461
+ region=context,
2462
+ keys=('pod_config',),
2463
+ default_value={})
2464
+ override_pod_config = config_utils.get_cloud_config_value_from_dict(
2465
+ dict_config=cluster_config_overrides,
2466
+ cloud='kubernetes',
2467
+ region=context,
2468
+ keys=('pod_config',),
2469
+ default_value={})
2454
2470
  config_utils.merge_k8s_configs(kubernetes_config, override_pod_config)
2455
2471
 
2456
2472
  # Merge the kubernetes config into the YAML for both head and worker nodes.
@@ -2462,7 +2478,8 @@ def combine_pod_config_fields(
2462
2478
  common_utils.dump_yaml(cluster_yaml_path, yaml_obj)
2463
2479
 
2464
2480
 
2465
- def combine_metadata_fields(cluster_yaml_path: str) -> None:
2481
+ def combine_metadata_fields(cluster_yaml_path: str,
2482
+ context: Optional[str] = None) -> None:
2466
2483
  """Updates the metadata for all Kubernetes objects created by SkyPilot with
2467
2484
  fields from the ~/.sky/config.yaml's kubernetes.custom_metadata dict.
2468
2485
 
@@ -2472,8 +2489,11 @@ def combine_metadata_fields(cluster_yaml_path: str) -> None:
2472
2489
  with open(cluster_yaml_path, 'r', encoding='utf-8') as f:
2473
2490
  yaml_content = f.read()
2474
2491
  yaml_obj = yaml.safe_load(yaml_content)
2475
- custom_metadata = skypilot_config.get_nested(
2476
- ('kubernetes', 'custom_metadata'), {})
2492
+ custom_metadata = skypilot_config.get_effective_region_config(
2493
+ cloud='kubernetes',
2494
+ region=context,
2495
+ keys=('custom_metadata',),
2496
+ default_value={})
2477
2497
 
2478
2498
  # List of objects in the cluster YAML to be updated
2479
2499
  combination_destinations = [
@@ -2496,13 +2516,17 @@ def combine_metadata_fields(cluster_yaml_path: str) -> None:
2496
2516
  common_utils.dump_yaml(cluster_yaml_path, yaml_obj)
2497
2517
 
2498
2518
 
2499
- def merge_custom_metadata(original_metadata: Dict[str, Any]) -> None:
2519
+ def merge_custom_metadata(original_metadata: Dict[str, Any],
2520
+ context: Optional[str] = None) -> None:
2500
2521
  """Merges original metadata with custom_metadata from config
2501
2522
 
2502
2523
  Merge is done in-place, so return is not required
2503
2524
  """
2504
- custom_metadata = skypilot_config.get_nested(
2505
- ('kubernetes', 'custom_metadata'), {})
2525
+ custom_metadata = skypilot_config.get_effective_region_config(
2526
+ cloud='kubernetes',
2527
+ region=context,
2528
+ keys=('custom_metadata',),
2529
+ default_value={})
2506
2530
  config_utils.merge_k8s_configs(original_metadata, custom_metadata)
2507
2531
 
2508
2532
 
@@ -2556,7 +2580,7 @@ def create_namespace(namespace: str, context: Optional[str]) -> None:
2556
2580
  return
2557
2581
 
2558
2582
  ns_metadata = dict(name=namespace, labels={'parent': 'skypilot'})
2559
- merge_custom_metadata(ns_metadata)
2583
+ merge_custom_metadata(ns_metadata, context)
2560
2584
  namespace_obj = kubernetes_client.V1Namespace(metadata=ns_metadata)
2561
2585
  try:
2562
2586
  kubernetes.core_api(context).create_namespace(namespace_obj)
@@ -2582,15 +2606,14 @@ def get_head_pod_name(cluster_name_on_cloud: str):
2582
2606
  return f'{cluster_name_on_cloud}-head'
2583
2607
 
2584
2608
 
2585
- def get_autoscaler_type(
2586
- ) -> Optional[kubernetes_enums.KubernetesAutoscalerType]:
2587
- """Returns the autoscaler type by reading from config"""
2588
- autoscaler_type = skypilot_config.get_nested(('kubernetes', 'autoscaler'),
2589
- None)
2590
- if autoscaler_type is not None:
2591
- autoscaler_type = kubernetes_enums.KubernetesAutoscalerType(
2592
- autoscaler_type)
2593
- return autoscaler_type
2609
+ def get_custom_config_k8s_contexts() -> List[str]:
2610
+ """Returns the list of context names from the config"""
2611
+ contexts = skypilot_config.get_effective_region_config(
2612
+ cloud='kubernetes',
2613
+ region=None,
2614
+ keys=('context_configs',),
2615
+ default_value={})
2616
+ return [*contexts] or []
2594
2617
 
2595
2618
 
2596
2619
  # Mapping of known spot label keys and values for different cluster types
@@ -2602,6 +2625,21 @@ SPOT_LABEL_MAP = {
2602
2625
  }
2603
2626
 
2604
2627
 
2628
+ def get_autoscaler_type(
2629
+ context: Optional[str] = None
2630
+ ) -> Optional[kubernetes_enums.KubernetesAutoscalerType]:
2631
+ """Returns the autoscaler type by reading from config"""
2632
+ autoscaler_type = skypilot_config.get_effective_region_config(
2633
+ cloud='kubernetes',
2634
+ region=context,
2635
+ keys=('autoscaler',),
2636
+ default_value=None)
2637
+ if autoscaler_type is not None:
2638
+ autoscaler_type = kubernetes_enums.KubernetesAutoscalerType(
2639
+ autoscaler_type)
2640
+ return autoscaler_type
2641
+
2642
+
2605
2643
  def get_spot_label(
2606
2644
  context: Optional[str] = None) -> Tuple[Optional[str], Optional[str]]:
2607
2645
  """Get the spot label key and value for using spot instances, if supported.
@@ -2625,7 +2663,7 @@ def get_spot_label(
2625
2663
 
2626
2664
  # Check if autoscaler is configured. Allow spot instances if autoscaler type
2627
2665
  # is known to support spot instances.
2628
- autoscaler_type = get_autoscaler_type()
2666
+ autoscaler_type = get_autoscaler_type(context=context)
2629
2667
  if autoscaler_type == kubernetes_enums.KubernetesAutoscalerType.GKE:
2630
2668
  return SPOT_LABEL_MAP[autoscaler_type.value]
2631
2669