polyaxon 2.1.8__py3-none-any.whl → 2.2.0.post1__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 (58) hide show
  1. polyaxon/_cli/artifacts.py +16 -12
  2. polyaxon/_cli/components.py +16 -12
  3. polyaxon/_cli/config.py +31 -0
  4. polyaxon/_cli/dashboard.py +15 -2
  5. polyaxon/_cli/init.py +1 -1
  6. polyaxon/_cli/models.py +16 -12
  7. polyaxon/_cli/operations.py +100 -54
  8. polyaxon/_cli/project_versions.py +26 -5
  9. polyaxon/_cli/projects.py +23 -9
  10. polyaxon/_cli/run.py +29 -9
  11. polyaxon/_client/mixin.py +39 -0
  12. polyaxon/_client/project.py +22 -22
  13. polyaxon/_client/run.py +44 -25
  14. polyaxon/_compiler/contexts/ray_job.py +4 -2
  15. polyaxon/_deploy/schemas/proxy.py +1 -0
  16. polyaxon/_env_vars/getters/owner_entity.py +4 -2
  17. polyaxon/_env_vars/getters/project.py +4 -2
  18. polyaxon/_env_vars/getters/run.py +2 -2
  19. polyaxon/_env_vars/keys.py +1 -0
  20. polyaxon/_k8s/converter/base/main.py +1 -0
  21. polyaxon/_k8s/converter/common/accelerators.py +7 -4
  22. polyaxon/_k8s/converter/converters/ray_job.py +4 -2
  23. polyaxon/_k8s/custom_resources/setter.py +1 -1
  24. polyaxon/_local_process/__init__.py +0 -0
  25. polyaxon/_local_process/agent.py +6 -0
  26. polyaxon/_local_process/converter/__init__.py +1 -0
  27. polyaxon/_local_process/converter/base/__init__.py +1 -0
  28. polyaxon/_local_process/converter/base/base.py +140 -0
  29. polyaxon/_local_process/converter/base/containers.py +69 -0
  30. polyaxon/_local_process/converter/base/env_vars.py +253 -0
  31. polyaxon/_local_process/converter/base/init.py +414 -0
  32. polyaxon/_local_process/converter/base/main.py +74 -0
  33. polyaxon/_local_process/converter/base/mounts.py +82 -0
  34. polyaxon/_local_process/converter/converters/__init__.py +8 -0
  35. polyaxon/_local_process/converter/converters/job.py +40 -0
  36. polyaxon/_local_process/converter/converters/service.py +41 -0
  37. polyaxon/_local_process/converter/mixins.py +38 -0
  38. polyaxon/_local_process/executor.py +132 -0
  39. polyaxon/_local_process/process_types.py +39 -0
  40. polyaxon/_sdk/api/organizations_v1_api.py +8 -8
  41. polyaxon/_sdk/api/project_dashboards_v1_api.py +12 -12
  42. polyaxon/_sdk/api/project_searches_v1_api.py +12 -12
  43. polyaxon/_sdk/api/projects_v1_api.py +221 -44
  44. polyaxon/_sdk/api/runs_v1_api.py +156 -202
  45. polyaxon/_sdk/api/service_accounts_v1_api.py +4 -4
  46. polyaxon/_sdk/api/teams_v1_api.py +2827 -375
  47. polyaxon/_sdk/api/users_v1_api.py +231 -55
  48. polyaxon/_sdk/schemas/v1_settings_catalog.py +1 -0
  49. polyaxon/_sdk/schemas/v1_team.py +3 -0
  50. polyaxon/_sdk/schemas/v1_user.py +1 -2
  51. polyaxon/_utils/fqn_utils.py +25 -2
  52. polyaxon/pkg.py +1 -1
  53. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.post1.dist-info}/METADATA +8 -8
  54. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.post1.dist-info}/RECORD +58 -41
  55. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.post1.dist-info}/LICENSE +0 -0
  56. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.post1.dist-info}/WHEEL +0 -0
  57. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.post1.dist-info}/entry_points.txt +0 -0
  58. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.post1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,39 @@
1
+ from polyaxon import settings
2
+ from polyaxon._client.client import PolyaxonClient
3
+ from polyaxon._schemas.client import ClientConfig
4
+ from polyaxon._utils.fqn_utils import split_owner_team_space
5
+
6
+
7
+ class ClientMixin:
8
+ @property
9
+ def client(self):
10
+ if self._client:
11
+ return self._client
12
+ self._client = PolyaxonClient()
13
+ return self._client
14
+
15
+ def reset_client(self, **kwargs):
16
+ if not settings.CLIENT_CONFIG.in_cluster:
17
+ self._client = PolyaxonClient(
18
+ ClientConfig.patch_from(settings.CLIENT_CONFIG, **kwargs)
19
+ )
20
+
21
+ @property
22
+ def owner(self) -> str:
23
+ return self._owner
24
+
25
+ @property
26
+ def team(self):
27
+ return self._team
28
+
29
+ @property
30
+ def project(self) -> str:
31
+ return self._project
32
+
33
+ def set_project(self, project: str):
34
+ self._project = project
35
+
36
+ def set_owner(self, owner: str):
37
+ owner, team = split_owner_team_space(owner)
38
+ self._owner = owner
39
+ self._team = team
@@ -12,6 +12,7 @@ from clipped.utils.validation import validate_tags
12
12
 
13
13
  from polyaxon._client.client import PolyaxonClient
14
14
  from polyaxon._client.decorators import client_handler, get_global_or_inline_config
15
+ from polyaxon._client.mixin import ClientMixin
15
16
  from polyaxon._constants.globals import DEFAULT
16
17
  from polyaxon._contexts import paths as ctx_paths
17
18
  from polyaxon._env_vars.getters.user import get_local_owner
@@ -21,13 +22,17 @@ from polyaxon._sdk.schemas.v1_list_project_versions_response import (
21
22
  )
22
23
  from polyaxon._sdk.schemas.v1_project import V1Project
23
24
  from polyaxon._sdk.schemas.v1_project_version import V1ProjectVersion
24
- from polyaxon._utils.fqn_utils import get_entity_full_name, get_entity_info
25
+ from polyaxon._utils.fqn_utils import (
26
+ get_entity_full_name,
27
+ get_entity_info,
28
+ split_owner_team_space,
29
+ )
25
30
  from polyaxon.exceptions import ApiException, PolyaxonClientException
26
31
  from polyaxon.logger import logger
27
32
  from traceml.artifacts import V1RunArtifact
28
33
 
29
34
 
30
- class ProjectClient:
35
+ class ProjectClient(ClientMixin):
31
36
  """ProjectClient is a client to communicate with Polyaxon projects endpoints.
32
37
 
33
38
  If no values are passed to this class,
@@ -94,26 +99,13 @@ class ProjectClient:
94
99
  if not owner:
95
100
  raise PolyaxonClientException("Please provide a valid owner.")
96
101
 
102
+ owner, team = split_owner_team_space(owner)
97
103
  self._client = client
98
104
  self._owner = owner or DEFAULT
105
+ self._team = team
99
106
  self._project = project
100
107
  self._project_data = V1Project.construct()
101
108
 
102
- @property
103
- def client(self):
104
- if self._client:
105
- return self._client
106
- self._client = PolyaxonClient()
107
- return self._client
108
-
109
- @property
110
- def owner(self):
111
- return self._owner
112
-
113
- @property
114
- def project(self):
115
- return self._project
116
-
117
109
  @property
118
110
  def project_data(self):
119
111
  return self._project_data
@@ -139,11 +131,19 @@ class ProjectClient:
139
131
  Returns:
140
132
  V1Project, project instance from the response.
141
133
  """
142
- self._project_data = self.client.projects_v1.create_project(
143
- self.owner,
144
- data,
145
- async_req=False,
146
- )
134
+ if self.team:
135
+ self._project_data = self.client.projects_v1.create_team_project(
136
+ self.owner,
137
+ self.team,
138
+ data,
139
+ async_req=False,
140
+ )
141
+ else:
142
+ self._project_data = self.client.projects_v1.create_project(
143
+ self.owner,
144
+ data,
145
+ async_req=False,
146
+ )
147
147
  self._project_data.owner = self.owner
148
148
  self._project = self._project_data.name
149
149
  return self._project_data
polyaxon/_client/run.py CHANGED
@@ -35,6 +35,7 @@ from polyaxon import settings
35
35
  from polyaxon._cli.errors import handle_cli_error
36
36
  from polyaxon._client.client import PolyaxonClient
37
37
  from polyaxon._client.decorators import client_handler, get_global_or_inline_config
38
+ from polyaxon._client.mixin import ClientMixin
38
39
  from polyaxon._client.store import PolyaxonStore
39
40
  from polyaxon._constants.metadata import META_COPY_ARTIFACTS, META_RECOMPILE
40
41
  from polyaxon._containers.names import MAIN_CONTAINER_NAMES
@@ -63,7 +64,11 @@ from polyaxon._sdk.schemas.v1_operation_body import V1OperationBody
63
64
  from polyaxon._sdk.schemas.v1_project_version import V1ProjectVersion
64
65
  from polyaxon._sdk.schemas.v1_run import V1Run
65
66
  from polyaxon._sdk.schemas.v1_run_settings import V1RunSettings
66
- from polyaxon._utils.fqn_utils import get_entity_full_name, to_fqn_name
67
+ from polyaxon._utils.fqn_utils import (
68
+ get_entity_full_name,
69
+ split_owner_team_space,
70
+ to_fqn_name,
71
+ )
67
72
  from polyaxon._utils.urls_utils import get_proxy_run_url
68
73
  from polyaxon.api import K8S_V1_LOCATION, STREAMS_V1_LOCATION
69
74
  from polyaxon.exceptions import ApiException, PolyaxonClientException
@@ -80,7 +85,7 @@ if TYPE_CHECKING:
80
85
  from traceml.tracking.run import Run
81
86
 
82
87
 
83
- class RunClient:
88
+ class RunClient(ClientMixin):
84
89
  """RunClient is a client to communicate with Polyaxon runs endpoints.
85
90
 
86
91
  If no values are passed to this class,
@@ -146,7 +151,7 @@ class RunClient:
146
151
  return
147
152
 
148
153
  try:
149
- owner, project = get_project_or_local(
154
+ owner, _, project = get_project_or_local(
150
155
  get_entity_full_name(owner=owner, entity=project)
151
156
  )
152
157
  except PolyaxonClientException:
@@ -166,8 +171,10 @@ class RunClient:
166
171
  if error_message and not self._is_offline:
167
172
  raise PolyaxonClientException(error_message)
168
173
 
174
+ owner, team = split_owner_team_space(owner)
169
175
  self._client = client
170
176
  self._owner = owner
177
+ self._team = team
171
178
  self._project = project
172
179
  self._run_uuid = (
173
180
  get_run_or_local(run_uuid)
@@ -218,12 +225,11 @@ class RunClient:
218
225
  return client.config.no_op
219
226
  return settings.CLIENT_CONFIG.no_op
220
227
 
221
- @property
222
- def client(self):
223
- if self._client:
224
- return self._client
225
- self._client = PolyaxonClient()
226
- return self._client
228
+ def _use_agent_host(self):
229
+ if self.settings.agent and self.settings.agent.url:
230
+ self.reset_client(
231
+ host=self.settings.agent.url, POLYAXON_HOST=self.settings.agent.url
232
+ )
227
233
 
228
234
  @property
229
235
  def store(self):
@@ -256,20 +262,6 @@ class RunClient:
256
262
  return self.settings.artifacts_store.name
257
263
  return None
258
264
 
259
- @property
260
- def owner(self) -> str:
261
- return self._owner or ""
262
-
263
- def set_owner(self, owner: str):
264
- self._owner = owner
265
-
266
- @property
267
- def project(self) -> str:
268
- return self._project or ""
269
-
270
- def set_project(self, project: str):
271
- self._project = project
272
-
273
265
  @property
274
266
  def run_uuid(self) -> str:
275
267
  return self._run_uuid
@@ -898,6 +890,7 @@ class RunClient:
898
890
  """
899
891
  if not self.settings:
900
892
  self.refresh_data()
893
+ self._use_agent_host()
901
894
  params = get_logs_params(
902
895
  last_file=last_file, last_time=last_time, connection=self.artifacts_store
903
896
  )
@@ -921,6 +914,7 @@ class RunClient:
921
914
  def inspect(self):
922
915
  if not self.settings:
923
916
  self.refresh_data()
917
+ self._use_agent_host()
924
918
  params = get_streams_params(connection=self.artifacts_store, status=self.status)
925
919
  return self.client.runs_v1.inspect_run(
926
920
  self.namespace, self.owner, self.project, self.run_uuid, **params
@@ -994,6 +988,10 @@ class RunClient:
994
988
  if not container:
995
989
  container = pod_containers[0]
996
990
 
991
+ if not self.settings:
992
+ self.refresh_data()
993
+ self._use_agent_host()
994
+
997
995
  url = get_proxy_run_url(
998
996
  service=K8S_V1_LOCATION,
999
997
  namespace=self.namespace,
@@ -1039,6 +1037,8 @@ class RunClient:
1039
1037
  """
1040
1038
  if not self.settings:
1041
1039
  self.refresh_data()
1040
+ self._use_agent_host()
1041
+
1042
1042
  params = get_streams_params(self.artifacts_store)
1043
1043
  return self.client.runs_v1.get_run_events(
1044
1044
  self.namespace,
@@ -1074,6 +1074,8 @@ class RunClient:
1074
1074
  """
1075
1075
  if not self.settings:
1076
1076
  self.refresh_data()
1077
+ self._use_agent_host()
1078
+
1077
1079
  params = get_streams_params(self.artifacts_store)
1078
1080
  return self.client.runs_v1.get_multi_run_events(
1079
1081
  self.namespace,
@@ -1310,6 +1312,7 @@ class RunClient:
1310
1312
  """
1311
1313
  if not self.settings:
1312
1314
  self.refresh_data()
1315
+ self._use_agent_host()
1313
1316
  params = get_streams_params(self.artifacts_store)
1314
1317
  return self.client.runs_v1.get_run_artifact(
1315
1318
  namespace=self.namespace,
@@ -1343,6 +1346,10 @@ class RunClient:
1343
1346
  if not self.run_uuid:
1344
1347
  return
1345
1348
 
1349
+ if not self.settings:
1350
+ self.refresh_data()
1351
+ self._use_agent_host()
1352
+
1346
1353
  lineage_path = lineage.path or ""
1347
1354
  summary = lineage.summary or {}
1348
1355
  is_event = summary.get("is_event")
@@ -1421,6 +1428,8 @@ class RunClient:
1421
1428
  """
1422
1429
  if not self.settings:
1423
1430
  self.refresh_data()
1431
+ self._use_agent_host()
1432
+
1424
1433
  url = get_proxy_run_url(
1425
1434
  service=STREAMS_V1_LOCATION,
1426
1435
  namespace=self.namespace,
@@ -1460,6 +1469,8 @@ class RunClient:
1460
1469
  """
1461
1470
  if not self.settings:
1462
1471
  self.refresh_data()
1472
+ self._use_agent_host()
1473
+
1463
1474
  url = get_proxy_run_url(
1464
1475
  service=STREAMS_V1_LOCATION,
1465
1476
  namespace=self.namespace,
@@ -1507,6 +1518,7 @@ class RunClient:
1507
1518
  """
1508
1519
  if not self.settings:
1509
1520
  self.refresh_data()
1521
+ self._use_agent_host()
1510
1522
 
1511
1523
  params = get_streams_params(connection=self.artifacts_store)
1512
1524
  url = get_proxy_run_url(
@@ -1596,6 +1608,7 @@ class RunClient:
1596
1608
 
1597
1609
  if not self.settings:
1598
1610
  self.refresh_data()
1611
+ self._use_agent_host()
1599
1612
 
1600
1613
  params = get_streams_params(connection=self.artifacts_store)
1601
1614
  url = get_proxy_run_url(
@@ -1626,6 +1639,8 @@ class RunClient:
1626
1639
  """
1627
1640
  if not self.settings:
1628
1641
  self.refresh_data()
1642
+ self._use_agent_host()
1643
+
1629
1644
  params = get_streams_params(connection=self.artifacts_store)
1630
1645
  self.client.runs_v1.delete_run_artifact(
1631
1646
  namespace=self.namespace,
@@ -1645,6 +1660,8 @@ class RunClient:
1645
1660
  """
1646
1661
  if not self.settings:
1647
1662
  self.refresh_data()
1663
+ self._use_agent_host()
1664
+
1648
1665
  params = get_streams_params(connection=self.artifacts_store)
1649
1666
  return self.client.runs_v1.delete_run_artifacts(
1650
1667
  namespace=self.namespace,
@@ -1667,6 +1684,8 @@ class RunClient:
1667
1684
  """
1668
1685
  if not self.settings:
1669
1686
  self.refresh_data()
1687
+ self._use_agent_host()
1688
+
1670
1689
  params = get_streams_params(connection=self.artifacts_store)
1671
1690
  return self.client.runs_v1.get_run_artifacts_tree(
1672
1691
  namespace=self.namespace,
@@ -2117,9 +2136,9 @@ class RunClient:
2117
2136
  abspath = filepath if is_abs() else os.path.abspath(filepath)
2118
2137
 
2119
2138
  for_patterns = []
2120
- if getattr(self, "_artifacts_path"):
2139
+ if getattr(self, "_artifacts_path", None):
2121
2140
  for_patterns.append(getattr(self, "_artifacts_path"))
2122
- if getattr(self, "_store_path"):
2141
+ if getattr(self, "_store_path", None):
2123
2142
  for_patterns.append(getattr(self, "_store_path"))
2124
2143
  context_root = (
2125
2144
  ctx_paths.CONTEXT_OFFLINE_ROOT
@@ -33,7 +33,9 @@ class RayJobContextsManager(BaseContextsManager):
33
33
  connection_by_names=connection_by_names,
34
34
  )
35
35
 
36
- return {
36
+ data = {
37
37
  "head": _get_replica(job.head),
38
- "workers": {wn: _get_replica(job.workers[wn]) for wn in job.workers},
39
38
  }
39
+ if job.workers:
40
+ data["workers"] = {wn: _get_replica(job.workers[wn]) for wn in job.workers}
41
+ return data
@@ -13,4 +13,5 @@ class ProxyConfig(BaseSchemaModel):
13
13
  no_proxy: Optional[StrictStr] = Field(alias="noProxy")
14
14
  port: Optional[StrictInt]
15
15
  host: Optional[StrictStr]
16
+ protocol: Optional[StrictStr]
16
17
  kind: Optional[StrictStr]
@@ -5,7 +5,7 @@ from clipped.utils.strings import validate_slug
5
5
 
6
6
  from polyaxon._constants.globals import DEFAULT
7
7
  from polyaxon._env_vars.getters.user import get_local_owner
8
- from polyaxon._utils.fqn_utils import get_entity_info
8
+ from polyaxon._utils.fqn_utils import get_entity_info, split_owner_team_space
9
9
  from polyaxon.exceptions import PolyaxonClientException, PolyaxonSchemaError
10
10
 
11
11
 
@@ -31,6 +31,8 @@ def resolve_entity_info(entity: str, entity_name: str, is_cli: bool = False):
31
31
  if not owner:
32
32
  owner = settings.AUTH_CONFIG.username if settings.AUTH_CONFIG else None
33
33
 
34
+ owner, team = split_owner_team_space(owner)
35
+
34
36
  if not all([owner, entity_value]):
35
37
  message = "Please provide a valid {}.".format(entity_name)
36
38
  if is_cli:
@@ -49,4 +51,4 @@ def resolve_entity_info(entity: str, entity_name: str, is_cli: bool = False):
49
51
  entity_name, entity_value
50
52
  )
51
53
  )
52
- return owner, entity_value
54
+ return owner, team, entity_value
@@ -7,7 +7,7 @@ from polyaxon._constants.globals import DEFAULT
7
7
  from polyaxon._env_vars.getters.user import get_local_owner
8
8
  from polyaxon._managers.project import ProjectConfigManager
9
9
  from polyaxon._utils.cache import get_local_project
10
- from polyaxon._utils.fqn_utils import get_entity_info
10
+ from polyaxon._utils.fqn_utils import get_entity_info, split_owner_team_space
11
11
  from polyaxon.exceptions import PolyaxonClientException, PolyaxonSchemaError
12
12
 
13
13
 
@@ -52,6 +52,8 @@ def get_project_or_local(project=None, is_cli: bool = False):
52
52
  if not owner and (not settings.CLI_CONFIG or settings.CLI_CONFIG.is_community):
53
53
  owner = DEFAULT
54
54
 
55
+ owner, team = split_owner_team_space(owner)
56
+
55
57
  if not all([owner, project_name]):
56
58
  error_message = get_project_error_message(owner, project_name)
57
59
  if is_cli:
@@ -79,4 +81,4 @@ def get_project_or_local(project=None, is_cli: bool = False):
79
81
  sys.exit(1)
80
82
  else:
81
83
  raise PolyaxonSchemaError(error_message)
82
- return owner, project_name
84
+ return owner, team, project_name
@@ -37,9 +37,9 @@ def get_run_or_local(run_uuid=None, is_cli: bool = False):
37
37
 
38
38
 
39
39
  def get_project_run_or_local(project=None, run_uuid=None, is_cli: bool = True):
40
- user, project_name = get_project_or_local(project, is_cli=is_cli)
40
+ owner, team, project_name = get_project_or_local(project, is_cli=is_cli)
41
41
  run_uuid = get_run_or_local(run_uuid, is_cli=is_cli)
42
- return user, project_name, run_uuid
42
+ return owner, team, project_name, run_uuid
43
43
 
44
44
 
45
45
  def get_collect_artifacts(arg: Optional[bool] = None, default: Optional[bool] = None):
@@ -141,6 +141,7 @@ ENV_KEYS_PROXY_AUTH_USE_RESOLVER = "POLYAXON_PROXY_AUTH_USE_RESOLVER"
141
141
  ENV_KEYS_PROXY_HAS_FORWARD_PROXY = "POLYAXON_PROXY_HAS_FORWARD_PROXY"
142
142
  ENV_KEYS_PROXY_FORWARD_PROXY_PORT = "POLYAXON_PROXY_FORWARD_PROXY_PORT"
143
143
  ENV_KEYS_PROXY_FORWARD_PROXY_HOST = "POLYAXON_PROXY_FORWARD_PROXY_HOST"
144
+ ENV_KEYS_PROXY_FORWARD_PROXY_PROTOCOL = "POLYAXON_PROXY_FORWARD_PROXY_PROTOCOL"
144
145
  ENV_KEYS_PROXY_FORWARD_PROXY_KIND = "POLYAXON_PROXY_FORWARD_PROXY_KIND"
145
146
  ENV_KEYS_UI_IN_SANDBOX = "POLYAXON_UI_IN_SANDBOX"
146
147
  ENV_KEYS_UI_ADMIN_ENABLED = "POLYAXON_UI_ADMIN_ENABLED"
@@ -81,6 +81,7 @@ class MainConverter(_BaseConverter):
81
81
  secrets=requested_secrets,
82
82
  config_maps=requested_config_maps,
83
83
  )
84
+ env += self._get_resources_env_vars(main_container.resources)
84
85
 
85
86
  # Env from
86
87
  env_from = self._get_env_from_k8s_resources(
@@ -37,14 +37,17 @@ def requests_gpu(resources: k8s_schemas.V1ResourceRequirements) -> bool:
37
37
  if not resources:
38
38
  return False
39
39
 
40
+ if not isinstance(resources, k8s_schemas.V1ResourceRequirements):
41
+ resources = k8s_schemas.V1ResourceRequirements(**resources)
42
+
40
43
  if resources.requests:
41
- for key in resources.requests.keys():
42
- if "gpu" in key:
44
+ for key, val in resources.requests.items():
45
+ if "gpu" in key and val is not None and val > 0:
43
46
  return True
44
47
 
45
48
  if resources.limits:
46
- for key in resources.limits.keys():
47
- if "gpu" in key:
49
+ for key, val in resources.limits.items():
50
+ if "gpu" in key and val is not None and val > 0:
48
51
  return True
49
52
 
50
53
  return False
@@ -58,7 +58,9 @@ class RayJobConverter(RayJobMixin, BaseConverter):
58
58
  config=compiled_operation.plugins, auth=default_auth
59
59
  )
60
60
  head = _get_replica(job.head)
61
- workers = {n: _get_replica(w) for n, w in job.workers.items()}
61
+ workers = None
62
+ if job.workers:
63
+ workers = {n: _get_replica(w) for n, w in job.workers.items()}
62
64
  labels = self.get_labels(version=pkg.VERSION, labels={})
63
65
 
64
66
  return get_ray_job_custom_resource(
@@ -68,7 +70,7 @@ class RayJobConverter(RayJobMixin, BaseConverter):
68
70
  workers=workers,
69
71
  entrypoint=job.entrypoint,
70
72
  metadata=job.metadata,
71
- runtime_env=encode(orjson_dumps(job.runtime_env)),
73
+ runtime_env=orjson_dumps(job.runtime_env),
72
74
  ray_version=job.ray_version,
73
75
  termination=compiled_operation.termination,
74
76
  collect_logs=plugins.collect_logs,
@@ -46,7 +46,7 @@ def set_notify(custom_object: Dict, notifications: List[V1Notification]) -> Dict
46
46
  def set_clean_pod_policy(template_spec: Dict, clean_pod_policy: str) -> Dict:
47
47
  if not clean_pod_policy:
48
48
  # Sets default clean pod policy
49
- clean_pod_policy = "All"
49
+ clean_pod_policy = "None"
50
50
 
51
51
  template_spec["cleanPodPolicy"] = clean_pod_policy.capitalize()
52
52
  return template_spec
File without changes
@@ -0,0 +1,6 @@
1
+ from polyaxon._local_process.executor import Executor
2
+ from polyaxon._runner.agent.sync_agent import BaseSyncAgent
3
+
4
+
5
+ class Agent(BaseSyncAgent):
6
+ EXECUTOR = Executor
@@ -0,0 +1 @@
1
+ from polyaxon._local_process.converter.base.base import BaseConverter
@@ -0,0 +1,140 @@
1
+ from typing import Dict, Iterable, List, Optional, Union
2
+
3
+ from polyaxon import settings
4
+ from polyaxon._auxiliaries import V1PolyaxonSidecarContainer
5
+ from polyaxon._connections import V1Connection, V1ConnectionResource
6
+ from polyaxon._flow import V1Environment, V1Init, V1Plugins
7
+ from polyaxon._k8s import k8s_schemas
8
+ from polyaxon._local_process import process_types
9
+ from polyaxon._local_process.converter.base.containers import ContainerMixin
10
+ from polyaxon._local_process.converter.base.env_vars import EnvMixin
11
+ from polyaxon._local_process.converter.base.init import InitConverter
12
+ from polyaxon._local_process.converter.base.main import MainConverter
13
+ from polyaxon._local_process.converter.base.mounts import MountsMixin
14
+ from polyaxon._runner.converter import BaseConverter as _BaseConverter
15
+ from polyaxon._runner.kinds import RunnerKind
16
+ from polyaxon.exceptions import PolyaxonConverterError
17
+
18
+
19
+ class BaseConverter(
20
+ MainConverter, InitConverter, ContainerMixin, EnvMixin, MountsMixin, _BaseConverter
21
+ ):
22
+ RUNNER_KIND = RunnerKind.PROCESS
23
+
24
+ @classmethod
25
+ def _get_sidecar_container(
26
+ cls,
27
+ container_id: str,
28
+ polyaxon_sidecar: V1PolyaxonSidecarContainer,
29
+ env: List[process_types.V1EnvVar],
30
+ artifacts_store: V1Connection,
31
+ plugins: V1Plugins,
32
+ run_path: Optional[str],
33
+ ) -> Optional[process_types.V1Container]:
34
+ return None
35
+
36
+ @classmethod
37
+ def _k8s_to_process_env_var(
38
+ cls,
39
+ env_var: List[k8s_schemas.V1EnvVar],
40
+ ) -> List[process_types.V1EnvVar]:
41
+ if not env_var:
42
+ return []
43
+
44
+ process_env_var = []
45
+ for item in env_var:
46
+ if isinstance(item, dict):
47
+ try:
48
+ item = k8s_schemas.V1EnvVar(**item)
49
+ except (ValueError, TypeError) as e:
50
+ raise PolyaxonConverterError(
51
+ f"Could not parse env var value `{item}` from the K8S schema in container section"
52
+ ) from e
53
+ process_env_var.append(cls._get_env_var(name=item.name, value=item.value))
54
+
55
+ return process_env_var
56
+
57
+ @staticmethod
58
+ def _new_container(name: str) -> process_types.V1Container:
59
+ return process_types.V1Container(name=name)
60
+
61
+ @classmethod
62
+ def _ensure_container(
63
+ cls,
64
+ container: Union[k8s_schemas.V1Container, process_types.V1Container],
65
+ volumes: List[k8s_schemas.V1Volume],
66
+ ) -> process_types.V1Container:
67
+ if not isinstance(container, k8s_schemas.V1Container):
68
+ return container
69
+ return process_types.V1Container(
70
+ name=container.name,
71
+ command=container.command,
72
+ args=container.args,
73
+ env=cls._k8s_to_process_env_var(container.env),
74
+ working_dir=container.working_dir,
75
+ )
76
+
77
+ def get_replica_resource(
78
+ self,
79
+ environment: V1Environment,
80
+ plugins: V1Plugins,
81
+ volumes: List[k8s_schemas.V1Volume],
82
+ init: List[V1Init],
83
+ sidecars: List[k8s_schemas.V1Container],
84
+ container: k8s_schemas.V1Container,
85
+ artifacts_store: V1Connection,
86
+ connections: List[str],
87
+ connection_by_names: Dict[str, V1Connection],
88
+ secrets: Optional[Iterable[V1ConnectionResource]],
89
+ config_maps: Optional[Iterable[V1ConnectionResource]],
90
+ kv_env_vars: List[List],
91
+ default_sa: Optional[str] = None,
92
+ ports: List[int] = None,
93
+ ) -> List[process_types.V1Container]:
94
+ volumes = volumes or []
95
+ init = init or []
96
+ sidecars = sidecars or []
97
+ connections = connections or []
98
+ environment = environment or V1Environment()
99
+ environment.service_account_name = (
100
+ environment.service_account_name
101
+ or default_sa
102
+ or settings.AGENT_CONFIG.runs_sa
103
+ )
104
+
105
+ init_connections = self.filter_connections_from_init(init=init)
106
+
107
+ init_containers = self.get_init_containers(
108
+ polyaxon_init=self.polyaxon_init,
109
+ plugins=plugins,
110
+ artifacts_store=artifacts_store,
111
+ init_connections=init_connections,
112
+ init_containers=self.filter_containers_from_init(init=init),
113
+ connection_by_names=connection_by_names,
114
+ log_level=plugins.log_level,
115
+ volumes=volumes,
116
+ )
117
+
118
+ sidecar_containers = self.get_sidecar_containers(
119
+ polyaxon_sidecar=self.polyaxon_sidecar,
120
+ plugins=plugins,
121
+ artifacts_store=artifacts_store,
122
+ sidecar_containers=sidecars,
123
+ log_level=plugins.log_level,
124
+ volumes=volumes,
125
+ )
126
+
127
+ main_container = self.get_main_container(
128
+ main_container=self._ensure_container(container, volumes=volumes),
129
+ plugins=plugins,
130
+ artifacts_store=artifacts_store,
131
+ connections=connections,
132
+ init_connections=init_connections,
133
+ connection_by_names=connection_by_names,
134
+ secrets=secrets,
135
+ config_maps=config_maps,
136
+ ports=ports,
137
+ kv_env_vars=kv_env_vars,
138
+ )
139
+
140
+ return init_containers + sidecar_containers + [main_container]