polyaxon 2.4.0rc1__py3-none-any.whl → 2.6.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.
Files changed (218) hide show
  1. polyaxon/_auxiliaries/default_scheduling.py +17 -7
  2. polyaxon/_auxiliaries/init.py +14 -6
  3. polyaxon/_auxiliaries/sidecar.py +10 -8
  4. polyaxon/_cli/dashboard.py +2 -5
  5. polyaxon/_cli/run.py +14 -0
  6. polyaxon/_cli/version.py +4 -1
  7. polyaxon/_compiler/contexts/contexts.py +4 -0
  8. polyaxon/_compiler/resolver/agent.py +10 -9
  9. polyaxon/_compiler/resolver/runtime.py +4 -0
  10. polyaxon/_constants/metadata.py +1 -0
  11. polyaxon/_contexts/keys.py +1 -0
  12. polyaxon/_deploy/schemas/auth.py +3 -3
  13. polyaxon/_deploy/schemas/celery.py +10 -8
  14. polyaxon/_deploy/schemas/deployment.py +148 -116
  15. polyaxon/_deploy/schemas/email.py +8 -8
  16. polyaxon/_deploy/schemas/ingress.py +7 -7
  17. polyaxon/_deploy/schemas/intervals.py +3 -1
  18. polyaxon/_deploy/schemas/operators.py +8 -8
  19. polyaxon/_deploy/schemas/proxy.py +9 -9
  20. polyaxon/_deploy/schemas/rbac.py +1 -1
  21. polyaxon/_deploy/schemas/root_user.py +5 -5
  22. polyaxon/_deploy/schemas/security_context.py +25 -15
  23. polyaxon/_deploy/schemas/service.py +73 -69
  24. polyaxon/_deploy/schemas/ssl.py +3 -3
  25. polyaxon/_deploy/schemas/ui.py +10 -6
  26. polyaxon/_docker/builder/builder.py +4 -1
  27. polyaxon/_docker/converter/base/containers.py +4 -7
  28. polyaxon/_docker/converter/base/env_vars.py +5 -5
  29. polyaxon/_docker/converter/base/mounts.py +2 -2
  30. polyaxon/_docker/docker_types.py +57 -30
  31. polyaxon/_env_vars/keys.py +2 -0
  32. polyaxon/_flow/__init__.py +3 -2
  33. polyaxon/_flow/builds/__init__.py +8 -8
  34. polyaxon/_flow/cache/__init__.py +4 -4
  35. polyaxon/_flow/component/base.py +25 -18
  36. polyaxon/_flow/component/component.py +4 -3
  37. polyaxon/_flow/early_stopping/__init__.py +1 -1
  38. polyaxon/_flow/early_stopping/policies.py +12 -10
  39. polyaxon/_flow/environment/__init__.py +42 -24
  40. polyaxon/_flow/events/__init__.py +1 -1
  41. polyaxon/_flow/hooks/__init__.py +11 -11
  42. polyaxon/_flow/init/__init__.py +41 -25
  43. polyaxon/_flow/io/io.py +57 -47
  44. polyaxon/_flow/joins/__init__.py +5 -5
  45. polyaxon/_flow/matrix/bayes.py +23 -17
  46. polyaxon/_flow/matrix/grid_search.py +16 -7
  47. polyaxon/_flow/matrix/hyperband.py +10 -10
  48. polyaxon/_flow/matrix/hyperopt.py +14 -9
  49. polyaxon/_flow/matrix/iterative.py +14 -8
  50. polyaxon/_flow/matrix/mapping.py +4 -4
  51. polyaxon/_flow/matrix/params.py +138 -77
  52. polyaxon/_flow/matrix/random_search.py +10 -5
  53. polyaxon/_flow/matrix/tuner.py +4 -4
  54. polyaxon/_flow/mounts/artifacts_mounts.py +1 -1
  55. polyaxon/_flow/notifications/__init__.py +1 -1
  56. polyaxon/_flow/operations/base.py +10 -8
  57. polyaxon/_flow/operations/compiled_operation.py +5 -4
  58. polyaxon/_flow/operations/operation.py +30 -22
  59. polyaxon/_flow/optimization/__init__.py +2 -2
  60. polyaxon/_flow/params/params.py +10 -9
  61. polyaxon/_flow/plugins/__init__.py +19 -13
  62. polyaxon/_flow/run/dag.py +12 -9
  63. polyaxon/_flow/run/dask/dask.py +4 -4
  64. polyaxon/_flow/run/dask/replica.py +17 -11
  65. polyaxon/_flow/run/job.py +17 -11
  66. polyaxon/_flow/run/kubeflow/mpi_job.py +10 -5
  67. polyaxon/_flow/run/kubeflow/mx_job.py +25 -9
  68. polyaxon/_flow/run/kubeflow/paddle_job.py +16 -9
  69. polyaxon/_flow/run/kubeflow/pytorch_job.py +24 -17
  70. polyaxon/_flow/run/kubeflow/replica.py +17 -11
  71. polyaxon/_flow/run/kubeflow/scheduling_policy.py +7 -5
  72. polyaxon/_flow/run/kubeflow/tf_job.py +15 -8
  73. polyaxon/_flow/run/kubeflow/xgboost_job.py +9 -4
  74. polyaxon/_flow/run/ray/ray.py +9 -6
  75. polyaxon/_flow/run/ray/replica.py +25 -16
  76. polyaxon/_flow/run/resources.py +14 -13
  77. polyaxon/_flow/run/service.py +4 -4
  78. polyaxon/_flow/schedules/cron.py +4 -4
  79. polyaxon/_flow/schedules/interval.py +4 -4
  80. polyaxon/_flow/templates/__init__.py +3 -3
  81. polyaxon/_flow/termination/__init__.py +3 -3
  82. polyaxon/_fs/async_manager.py +1 -1
  83. polyaxon/_fs/watcher.py +26 -27
  84. polyaxon/_k8s/k8s_validation.py +1 -1
  85. polyaxon/_k8s/logging/async_monitor.py +18 -3
  86. polyaxon/_local_process/converter/base/containers.py +4 -7
  87. polyaxon/_local_process/converter/base/env_vars.py +5 -5
  88. polyaxon/_local_process/process_types.py +15 -12
  89. polyaxon/_polyaxonfile/specs/compiled_operation.py +1 -1
  90. polyaxon/_polyaxonfile/specs/libs/parser.py +1 -1
  91. polyaxon/_polyaxonfile/specs/libs/validator.py +1 -1
  92. polyaxon/_polyaxonfile/specs/operation.py +1 -1
  93. polyaxon/_polyaxonfile/specs/sections.py +8 -0
  94. polyaxon/_runner/agent/async_agent.py +9 -6
  95. polyaxon/_runner/agent/base_agent.py +8 -5
  96. polyaxon/_runner/agent/sync_agent.py +8 -5
  97. polyaxon/_runner/converter/converter.py +12 -4
  98. polyaxon/_schemas/agent.py +69 -37
  99. polyaxon/_schemas/authentication.py +4 -4
  100. polyaxon/_schemas/base.py +26 -2
  101. polyaxon/_schemas/checks.py +3 -3
  102. polyaxon/_schemas/cli.py +4 -6
  103. polyaxon/_schemas/client.py +20 -18
  104. polyaxon/_schemas/compatibility.py +4 -4
  105. polyaxon/_schemas/container_resources.py +1 -1
  106. polyaxon/_schemas/home.py +3 -3
  107. polyaxon/_schemas/installation.py +13 -9
  108. polyaxon/_schemas/lifecycle.py +23 -23
  109. polyaxon/_schemas/log_handler.py +2 -2
  110. polyaxon/_schemas/services.py +26 -14
  111. polyaxon/_schemas/types/artifacts.py +3 -3
  112. polyaxon/_schemas/types/dockerfile.py +14 -12
  113. polyaxon/_schemas/types/event.py +2 -2
  114. polyaxon/_schemas/types/file.py +3 -3
  115. polyaxon/_schemas/types/git.py +12 -4
  116. polyaxon/_schemas/types/tensorboard.py +14 -8
  117. polyaxon/_schemas/user.py +3 -3
  118. polyaxon/_schemas/version.py +2 -2
  119. polyaxon/_sdk/api/agents_v1_api.py +45 -45
  120. polyaxon/_sdk/api/artifacts_stores_v1_api.py +3 -3
  121. polyaxon/_sdk/api/auth_v1_api.py +13 -13
  122. polyaxon/_sdk/api/connections_v1_api.py +15 -15
  123. polyaxon/_sdk/api/dashboards_v1_api.py +15 -15
  124. polyaxon/_sdk/api/organizations_v1_api.py +77 -77
  125. polyaxon/_sdk/api/presets_v1_api.py +15 -15
  126. polyaxon/_sdk/api/project_dashboards_v1_api.py +17 -17
  127. polyaxon/_sdk/api/project_searches_v1_api.py +17 -17
  128. polyaxon/_sdk/api/projects_v1_api.py +65 -65
  129. polyaxon/_sdk/api/queues_v1_api.py +19 -19
  130. polyaxon/_sdk/api/runs_v1_api.py +127 -127
  131. polyaxon/_sdk/api/searches_v1_api.py +15 -15
  132. polyaxon/_sdk/api/service_accounts_v1_api.py +27 -27
  133. polyaxon/_sdk/api/tags_v1_api.py +17 -17
  134. polyaxon/_sdk/api/teams_v1_api.py +51 -51
  135. polyaxon/_sdk/api/users_v1_api.py +25 -25
  136. polyaxon/_sdk/api/versions_v1_api.py +7 -7
  137. polyaxon/_sdk/schemas/v1_activity.py +8 -8
  138. polyaxon/_sdk/schemas/v1_agent.py +17 -16
  139. polyaxon/_sdk/schemas/v1_agent_state_response.py +4 -4
  140. polyaxon/_sdk/schemas/v1_agent_state_response_agent_state.py +10 -10
  141. polyaxon/_sdk/schemas/v1_agent_status_body_request.py +3 -3
  142. polyaxon/_sdk/schemas/v1_analytics_spec.py +4 -4
  143. polyaxon/_sdk/schemas/v1_artifact_tree.py +3 -3
  144. polyaxon/_sdk/schemas/v1_auth.py +1 -1
  145. polyaxon/_sdk/schemas/v1_cloning.py +3 -3
  146. polyaxon/_sdk/schemas/v1_connection_response.py +9 -9
  147. polyaxon/_sdk/schemas/v1_dashboard.py +9 -9
  148. polyaxon/_sdk/schemas/v1_dashboard_spec.py +5 -5
  149. polyaxon/_sdk/schemas/v1_entities_tags.py +2 -2
  150. polyaxon/_sdk/schemas/v1_entities_transfer.py +2 -2
  151. polyaxon/_sdk/schemas/v1_entity_notification_body.py +7 -7
  152. polyaxon/_sdk/schemas/v1_entity_stage_body_request.py +5 -5
  153. polyaxon/_sdk/schemas/v1_entity_status_body_request.py +5 -5
  154. polyaxon/_sdk/schemas/v1_events_response.py +2 -2
  155. polyaxon/_sdk/schemas/v1_list_activities_response.py +4 -4
  156. polyaxon/_sdk/schemas/v1_list_agents_response.py +4 -4
  157. polyaxon/_sdk/schemas/v1_list_bookmarks_response.py +4 -4
  158. polyaxon/_sdk/schemas/v1_list_connections_response.py +4 -4
  159. polyaxon/_sdk/schemas/v1_list_dashboards_response.py +4 -4
  160. polyaxon/_sdk/schemas/v1_list_organization_members_response.py +4 -4
  161. polyaxon/_sdk/schemas/v1_list_organizations_response.py +4 -4
  162. polyaxon/_sdk/schemas/v1_list_presets_response.py +4 -4
  163. polyaxon/_sdk/schemas/v1_list_project_versions_response.py +4 -4
  164. polyaxon/_sdk/schemas/v1_list_projects_response.py +4 -4
  165. polyaxon/_sdk/schemas/v1_list_queues_response.py +4 -4
  166. polyaxon/_sdk/schemas/v1_list_run_artifacts_response.py +4 -4
  167. polyaxon/_sdk/schemas/v1_list_run_connections_response.py +4 -4
  168. polyaxon/_sdk/schemas/v1_list_run_edges_response.py +4 -4
  169. polyaxon/_sdk/schemas/v1_list_runs_response.py +4 -4
  170. polyaxon/_sdk/schemas/v1_list_searches_response.py +4 -4
  171. polyaxon/_sdk/schemas/v1_list_service_accounts_response.py +4 -4
  172. polyaxon/_sdk/schemas/v1_list_tags_response.py +4 -4
  173. polyaxon/_sdk/schemas/v1_list_team_members_response.py +4 -4
  174. polyaxon/_sdk/schemas/v1_list_teams_response.py +4 -4
  175. polyaxon/_sdk/schemas/v1_list_token_response.py +4 -4
  176. polyaxon/_sdk/schemas/v1_operation_body.py +8 -8
  177. polyaxon/_sdk/schemas/v1_organization.py +16 -16
  178. polyaxon/_sdk/schemas/v1_organization_member.py +6 -6
  179. polyaxon/_sdk/schemas/v1_password_change.py +3 -3
  180. polyaxon/_sdk/schemas/v1_pipeline.py +3 -3
  181. polyaxon/_sdk/schemas/v1_preset.py +11 -12
  182. polyaxon/_sdk/schemas/v1_project.py +17 -17
  183. polyaxon/_sdk/schemas/v1_project_settings.py +11 -11
  184. polyaxon/_sdk/schemas/v1_project_version.py +20 -20
  185. polyaxon/_sdk/schemas/v1_queue.py +12 -12
  186. polyaxon/_sdk/schemas/v1_run.py +38 -38
  187. polyaxon/_sdk/schemas/v1_run_connection.py +3 -3
  188. polyaxon/_sdk/schemas/v1_run_edge.py +5 -5
  189. polyaxon/_sdk/schemas/v1_run_edge_lineage.py +3 -3
  190. polyaxon/_sdk/schemas/v1_run_edges_graph.py +1 -1
  191. polyaxon/_sdk/schemas/v1_run_reference_catalog.py +4 -4
  192. polyaxon/_sdk/schemas/v1_run_settings.py +9 -9
  193. polyaxon/_sdk/schemas/v1_search.py +10 -10
  194. polyaxon/_sdk/schemas/v1_search_spec.py +14 -14
  195. polyaxon/_sdk/schemas/v1_section_spec.py +12 -12
  196. polyaxon/_sdk/schemas/v1_service_account.py +9 -9
  197. polyaxon/_sdk/schemas/v1_settings_catalog.py +4 -4
  198. polyaxon/_sdk/schemas/v1_tag.py +6 -6
  199. polyaxon/_sdk/schemas/v1_team.py +11 -11
  200. polyaxon/_sdk/schemas/v1_team_member.py +6 -6
  201. polyaxon/_sdk/schemas/v1_team_settings.py +2 -2
  202. polyaxon/_sdk/schemas/v1_token.py +10 -10
  203. polyaxon/_sdk/schemas/v1_trial_start.py +6 -6
  204. polyaxon/_sdk/schemas/v1_user.py +6 -6
  205. polyaxon/_sdk/schemas/v1_user_access.py +7 -7
  206. polyaxon/_sdk/schemas/v1_user_email.py +1 -1
  207. polyaxon/_sdk/schemas/v1_user_singup.py +5 -5
  208. polyaxon/_sdk/schemas/v1_uuids.py +1 -1
  209. polyaxon/_sidecar/container/__init__.py +13 -8
  210. polyaxon/_utils/cli_constants.py +2 -0
  211. polyaxon/_utils/test_utils.py +2 -1
  212. polyaxon/pkg.py +1 -1
  213. {polyaxon-2.4.0rc1.dist-info → polyaxon-2.6.0.dist-info}/METADATA +13 -13
  214. {polyaxon-2.4.0rc1.dist-info → polyaxon-2.6.0.dist-info}/RECORD +218 -218
  215. {polyaxon-2.4.0rc1.dist-info → polyaxon-2.6.0.dist-info}/WHEEL +1 -1
  216. {polyaxon-2.4.0rc1.dist-info → polyaxon-2.6.0.dist-info}/LICENSE +0 -0
  217. {polyaxon-2.4.0rc1.dist-info → polyaxon-2.6.0.dist-info}/entry_points.txt +0 -0
  218. {polyaxon-2.4.0rc1.dist-info → polyaxon-2.6.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,12 @@
1
1
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
2
2
 
3
- from clipped.compact.pydantic import Field, StrictStr, validator
3
+ from clipped.compact.pydantic import (
4
+ Field,
5
+ StrictStr,
6
+ field_validator,
7
+ validation_always,
8
+ validation_before,
9
+ )
4
10
 
5
11
  from polyaxon._k8s import k8s_schemas, k8s_validation
6
12
  from polyaxon._schemas.base import BaseSchemaModel
@@ -13,16 +19,20 @@ class V1DefaultScheduling(BaseSchemaModel):
13
19
  _IDENTIFIER = "default_scheduling"
14
20
  _SWAGGER_FIELDS = ["affinity", "tolerations"]
15
21
 
16
- node_selector: Optional[Dict[StrictStr, StrictStr]] = Field(alias="nodeSelector")
17
- affinity: Optional[Union[k8s_schemas.V1Affinity, Dict]]
18
- tolerations: Optional[List[Union[k8s_schemas.V1Toleration, Dict]]]
19
- image_pull_secrets: Optional[List[StrictStr]] = Field(alias="imagePullSecrets")
22
+ node_selector: Optional[Dict[StrictStr, StrictStr]] = Field(
23
+ alias="nodeSelector", default=None
24
+ )
25
+ affinity: Optional[Union[k8s_schemas.V1Affinity, Dict]] = None
26
+ tolerations: Optional[List[Union[k8s_schemas.V1Toleration, Dict]]] = None
27
+ image_pull_secrets: Optional[List[StrictStr]] = Field(
28
+ alias="imagePullSecrets", default=None
29
+ )
20
30
 
21
- @validator("affinity", always=True, pre=True)
31
+ @field_validator("affinity", **validation_always, **validation_before)
22
32
  def validate_affinity(cls, v) -> k8s_schemas.V1Affinity:
23
33
  return k8s_validation.validate_k8s_affinity(v)
24
34
 
25
- @validator("tolerations", always=True, pre=True)
35
+ @field_validator("tolerations", **validation_always, **validation_before)
26
36
  def validate_tolerations(cls, v) -> List[k8s_schemas.V1Toleration]:
27
37
  if not v:
28
38
  return v
@@ -1,6 +1,12 @@
1
1
  from typing import Dict, Optional, Union
2
2
 
3
- from clipped.compact.pydantic import Field, StrictStr, validator
3
+ from clipped.compact.pydantic import (
4
+ Field,
5
+ StrictStr,
6
+ field_validator,
7
+ validation_always,
8
+ validation_before,
9
+ )
4
10
  from clipped.utils.versions import clean_version_post_suffix
5
11
 
6
12
  from polyaxon import pkg
@@ -93,12 +99,14 @@ class V1PolyaxonInitContainer(BaseSchemaModel):
93
99
  _IDENTIFIER = "container"
94
100
  _SWAGGER_FIELDS = ["resources"]
95
101
 
96
- image: Optional[StrictStr]
97
- image_tag: Optional[StrictStr] = Field(alias="imageTag")
98
- image_pull_policy: Optional[PullPolicy] = Field(alias="imagePullPolicy")
99
- resources: Optional[Union[k8s_schemas.V1ResourceRequirements, Dict]]
102
+ image: Optional[StrictStr] = None
103
+ image_tag: Optional[StrictStr] = Field(alias="imageTag", default=None)
104
+ image_pull_policy: Optional[PullPolicy] = Field(
105
+ alias="imagePullPolicy", default=None
106
+ )
107
+ resources: Optional[Union[k8s_schemas.V1ResourceRequirements, Dict]] = None
100
108
 
101
- @validator("resources", always=True, pre=True)
109
+ @field_validator("resources", **validation_always, **validation_before)
102
110
  def validate_resources(cls, v) -> k8s_schemas.V1ResourceRequirements:
103
111
  return k8s_validation.validate_k8s_resource_requirements(v)
104
112
 
@@ -147,14 +147,16 @@ class V1PolyaxonSidecarContainer(BaseSchemaModel):
147
147
 
148
148
  _IDENTIFIER = "polyaxon_sidecar"
149
149
 
150
- image: Optional[StrictStr]
151
- image_tag: Optional[StrictStr] = Field(alias="imageTag")
152
- image_pull_policy: Optional[PullPolicy] = Field(alias="imagePullPolicy")
153
- sleep_interval: Optional[IntOrRef] = Field(alias="sleepInterval")
154
- sync_interval: Optional[IntOrRef] = Field(alias="syncInterval")
155
- monitor_logs: Optional[BoolOrRef] = Field(alias="monitorLogs")
156
- monitor_spec: Optional[BoolOrRef] = Field(alias="monitorSpec")
157
- resources: Optional[Union[Dict[str, Any], RefField]]
150
+ image: Optional[StrictStr] = None
151
+ image_tag: Optional[StrictStr] = Field(alias="imageTag", default=None)
152
+ image_pull_policy: Optional[PullPolicy] = Field(
153
+ alias="imagePullPolicy", default=None
154
+ )
155
+ sleep_interval: Optional[IntOrRef] = Field(alias="sleepInterval", default=None)
156
+ sync_interval: Optional[IntOrRef] = Field(alias="syncInterval", default=None)
157
+ monitor_logs: Optional[BoolOrRef] = Field(alias="monitorLogs", default=None)
158
+ monitor_spec: Optional[BoolOrRef] = Field(alias="monitorSpec", default=None)
159
+ resources: Optional[Union[Dict[str, Any], RefField]] = None
158
160
 
159
161
  def get_image(self):
160
162
  image = self.image or "polyaxon/polyaxon-sidecar"
@@ -22,11 +22,8 @@ def get_dashboard_url(
22
22
  base: str = "ui", subpath: str = "", use_cloud: bool = False, host: str = None
23
23
  ) -> str:
24
24
  if not host:
25
- host = (
26
- POLYAXON_CLOUD_HOST
27
- if use_cloud
28
- else clean_host(settings.CLIENT_CONFIG.host)
29
- )
25
+ host = POLYAXON_CLOUD_HOST if use_cloud else settings.CLIENT_CONFIG.host
26
+ host = clean_host(host)
30
27
  dashboard_url = "{}/{}/".format(host, base)
31
28
  if subpath:
32
29
  return "{}{}/".format(dashboard_url, subpath.rstrip("/"))
polyaxon/_cli/run.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ import time
2
3
 
3
4
  from collections import namedtuple
4
5
  from typing import Dict, List, Optional
@@ -56,6 +57,7 @@ def _run(
56
57
  upload_to: str,
57
58
  upload_from: str,
58
59
  watch: bool,
60
+ approve_after: Optional[int] = None,
59
61
  output: Optional[str] = None,
60
62
  local: Optional[bool] = False,
61
63
  executor: Optional[RunnerKind] = None,
@@ -167,6 +169,9 @@ def _run(
167
169
  ctx.invoke(
168
170
  run_upload, path_to=upload_to, path_from=upload_from, sync_failure=True
169
171
  )
172
+ if approve_after and approve_after > 0:
173
+ Printer.print(f"Waiting {approve_after}s to approve the run...")
174
+ time.sleep(approve_after)
170
175
  ctx.invoke(approve)
171
176
 
172
177
  if not output:
@@ -375,11 +380,18 @@ def _run(
375
380
  )
376
381
  @click.option(
377
382
  "--approved",
383
+ "-ap",
378
384
  help="To enable/disable human in the loop validation without changing the polyaxonfile, "
379
385
  "similar to 'isApproved: true/false'. "
380
386
  "Can be used with yes/no, y/n, false/true, f/t, 1/0. "
381
387
  "e.g. '--approved=1', '--approved=yes', '--approved=false', '--approved=t', ...",
382
388
  )
389
+ @click.option(
390
+ "--approve-after",
391
+ "-aa",
392
+ type=int,
393
+ help="To delay or automatically approve a run after a certain number of seconds.",
394
+ )
383
395
  @click.option(
384
396
  "--git-preset",
385
397
  is_flag=True,
@@ -441,6 +453,7 @@ def run(
441
453
  nocache,
442
454
  cache,
443
455
  approved,
456
+ approve_after,
444
457
  git_preset,
445
458
  git_revision,
446
459
  ignore_template,
@@ -591,6 +604,7 @@ def run(
591
604
  upload_to=upload_to,
592
605
  upload_from=upload_from,
593
606
  watch=watch,
607
+ approve_after=approve_after,
594
608
  output=output,
595
609
  shell=shell,
596
610
  local=local,
polyaxon/_cli/version.py CHANGED
@@ -21,7 +21,10 @@ def pip_upgrade(project_name=PROJECT_CLI_NAME):
21
21
 
22
22
 
23
23
  def get_version(package: str, show_error: bool = True):
24
- import pkg_resources
24
+ try:
25
+ import pkg_resources
26
+ except ImportError:
27
+ return
25
28
 
26
29
  try:
27
30
  return pkg_resources.get_distribution(package).version
@@ -61,6 +61,7 @@ def resolve_globals_contexts(
61
61
  cloning_kind: V1CloningKind = None,
62
62
  original_uuid: Optional[str] = None,
63
63
  is_independent: bool = True,
64
+ username: Optional[str] = None,
64
65
  ) -> Dict:
65
66
  resolved_contexts = {
66
67
  ctx_sections.GLOBALS: {
@@ -70,6 +71,7 @@ def resolve_globals_contexts(
70
71
  owner_name, project_name
71
72
  ),
72
73
  ctx_keys.PROJECT_UUID: project_uuid,
74
+ ctx_keys.USERNAME: username,
73
75
  ctx_keys.RUN_INFO: get_run_instance(owner_name, project_name, run_uuid),
74
76
  ctx_keys.NAME: run_name,
75
77
  ctx_keys.UUID: run_uuid,
@@ -138,6 +140,7 @@ def resolve_contexts(
138
140
  cloning_kind: V1CloningKind = None,
139
141
  original_uuid: Optional[str] = None,
140
142
  is_independent: bool = True,
143
+ username: Optional[str] = None,
141
144
  ) -> Dict:
142
145
  run_kind = compiled_operation.get_run_kind()
143
146
  if run_kind not in CONTEXTS_MANAGERS:
@@ -168,6 +171,7 @@ def resolve_contexts(
168
171
  cloning_kind=cloning_kind,
169
172
  original_uuid=original_uuid,
170
173
  is_independent=is_independent,
174
+ username=username,
171
175
  )
172
176
 
173
177
  return CONTEXTS_MANAGERS[run_kind].resolve(
@@ -1,7 +1,8 @@
1
- from typing import Dict, List, Optional
1
+ from typing import Dict, List, Optional, Union
2
2
 
3
3
  from clipped.compact.pydantic import Field
4
4
  from clipped.utils.lists import to_list
5
+ from vents.connections import Connection, ConnectionResource
5
6
 
6
7
  from polyaxon import settings
7
8
  from polyaxon._auxiliaries import (
@@ -18,14 +19,14 @@ from polyaxon.exceptions import PolyaxonCompilerError
18
19
 
19
20
 
20
21
  class AgentResolver(BaseSchemaModel):
21
- polyaxon_sidecar: Optional[V1PolyaxonSidecarContainer]
22
- polyaxon_init: Optional[V1PolyaxonInitContainer]
23
- namespace: Optional[str]
24
- secrets: Optional[List[V1ConnectionResource]]
25
- config_maps: Optional[List[V1ConnectionResource]]
26
- connection_by_names: Optional[Dict[str, V1Connection]]
27
- artifacts_store: Optional[V1Connection]
28
- default_sa: Optional[str]
22
+ polyaxon_sidecar: Optional[V1PolyaxonSidecarContainer] = None
23
+ polyaxon_init: Optional[V1PolyaxonInitContainer] = None
24
+ namespace: Optional[str] = None
25
+ secrets: Optional[List[Union[V1ConnectionResource, ConnectionResource]]] = None
26
+ config_maps: Optional[List[Union[V1ConnectionResource, ConnectionResource]]] = None
27
+ connection_by_names: Optional[Dict[str, Union[V1Connection, Connection]]] = None
28
+ artifacts_store: Optional[Union[V1Connection, Connection]] = None
29
+ default_sa: Optional[str] = None
29
30
  internal_auth: Optional[bool] = Field(default=False)
30
31
 
31
32
  def resolve(
@@ -46,12 +46,14 @@ class BaseResolver:
46
46
  cloning_kind: V1CloningKind = None,
47
47
  original_uuid: Optional[str] = None,
48
48
  is_independent: bool = True,
49
+ username: Optional[str] = None,
49
50
  ):
50
51
  if not compiled_operation:
51
52
  raise PolyaxonCompilerError("A run spec is required for resolution.")
52
53
  self.run = run
53
54
  self.compiled_operation = compiled_operation
54
55
  self.owner_name = owner_name
56
+ self.username = username
55
57
  self.project_name = project_name
56
58
  self.project_uuid = project_uuid
57
59
  self.project_uuid = project_uuid or project_name
@@ -105,6 +107,7 @@ class BaseResolver:
105
107
  owner_name=self.owner_name,
106
108
  project_name=self.project_name,
107
109
  project_uuid=self.project_uuid,
110
+ username=self.username,
108
111
  run_uuid=self.run_uuid,
109
112
  run_name=self.run_name,
110
113
  run_path=self.run_path,
@@ -232,6 +235,7 @@ class BaseResolver:
232
235
  cloning_kind=self.cloning_kind,
233
236
  original_uuid=self.original_uuid,
234
237
  is_independent=self.is_independent,
238
+ username=self.username,
235
239
  )
236
240
 
237
241
  def _apply_runtime_contexts(self):
@@ -22,3 +22,4 @@ META_COPY_ARTIFACTS = "copy_artifacts"
22
22
  META_DESTINATION_IMAGE = "destination_image"
23
23
  META_PROGRESS = "progress"
24
24
  META_RECOMPILE = "recompile"
25
+ META_TTL = "ttl"
@@ -2,6 +2,7 @@ OWNER_NAME = "owner_name"
2
2
  PROJECT_NAME = "project_name"
3
3
  PROJECT_UUID = "project_uuid"
4
4
  PROJECT_UNIQUE_NAME = "project_unique_name"
5
+ USERNAME = "username"
5
6
  CONTEXT_PATH = "context_path"
6
7
  ARTIFACTS_PATH = "artifacts_path"
7
8
  ITERATION = "iteration"
@@ -6,6 +6,6 @@ from polyaxon._schemas.base import BaseSchemaModel
6
6
 
7
7
 
8
8
  class AuthConfig(BaseSchemaModel):
9
- enabled: Optional[bool]
10
- external: Optional[StrictStr]
11
- use_resolver: Optional[bool] = Field(alias="useResolver")
9
+ enabled: Optional[bool] = None
10
+ external: Optional[StrictStr] = None
11
+ use_resolver: Optional[bool] = Field(alias="useResolver", default=None)
@@ -6,17 +6,19 @@ from polyaxon._schemas.base import BaseSchemaModel
6
6
 
7
7
 
8
8
  class CeleryConfig(BaseSchemaModel):
9
- enabled: Optional[bool]
10
- task_track_started: Optional[bool] = Field(alias="taskTrackStarted")
11
- broker_pool_limit: Optional[StrictInt] = Field(alias="brokerPoolLimit")
12
- confirm_publish: Optional[bool] = Field(alias="confirmPublish")
9
+ enabled: Optional[bool] = None
10
+ task_track_started: Optional[bool] = Field(alias="taskTrackStarted", default=None)
11
+ broker_pool_limit: Optional[StrictInt] = Field(
12
+ alias="brokerPoolLimit", default=None
13
+ )
14
+ confirm_publish: Optional[bool] = Field(alias="confirmPublish", default=None)
13
15
  worker_prefetch_multiplier: Optional[StrictInt] = Field(
14
- alias="workerPrefetchMultiplier"
16
+ alias="workerPrefetchMultiplier", default=None
15
17
  )
16
18
  worker_max_tasks_per_child: Optional[StrictInt] = Field(
17
- alias="workerMaxTasksPerChild"
19
+ alias="workerMaxTasksPerChild", default=None
18
20
  )
19
21
  worker_max_memory_per_child: Optional[StrictInt] = Field(
20
- alias="workerMaxMemoryPerChild"
22
+ alias="workerMaxMemoryPerChild", default=None
21
23
  )
22
- task_always_eager: Optional[bool] = Field(alias="taskAlwaysEager")
24
+ task_always_eager: Optional[bool] = Field(alias="taskAlwaysEager", default=None)
@@ -5,8 +5,11 @@ from clipped.compact.pydantic import (
5
5
  Field,
6
6
  StrictInt,
7
7
  StrictStr,
8
- root_validator,
9
- validator,
8
+ field_validator,
9
+ model_validator,
10
+ validation_after,
11
+ validation_always,
12
+ validation_before,
10
13
  )
11
14
  from clipped.formatting import Printer
12
15
 
@@ -187,146 +190,175 @@ class DeploymentConfig(BaseSchemaModel):
187
190
  "celeryAffinity",
188
191
  ]
189
192
 
190
- deployment_type: Optional[DeploymentTypes] = Field(alias="deploymentType")
193
+ deployment_type: Optional[DeploymentTypes] = Field(
194
+ alias="deploymentType", default=None
195
+ )
191
196
  deployment_chart: Optional[DeploymentCharts] = Field(
192
197
  default=DeploymentCharts.PLATFORM, alias="deploymentChart"
193
198
  )
194
- deployment_version: Optional[StrictStr] = Field(alias="deploymentVersion")
195
- release_name: Optional[StrictStr] = Field(alias="releaseName")
196
- namespace: Optional[StrictStr]
197
- rbac: Optional[RBACConfig]
198
- polyaxon_secret: Optional[StrictStr] = Field(alias="polyaxonSecret")
199
- internal_token: Optional[StrictStr] = Field(alias="internalToken")
200
- password_length: Optional[StrictInt] = Field(alias="passwordLength")
201
- password_auth: Optional[bool] = Field(alias="passwordAuth")
202
- ssl: Optional[SSLConfig]
203
- encryption_secret: Optional[StrictStr] = Field(alias="encryptionSecret")
204
- platform_secret: Optional[StrictStr] = Field(alias="platformSecret")
205
- agent_secret: Optional[StrictStr] = Field(alias="agentSecret")
206
- timezone: Optional[StrictStr]
207
- environment: Optional[StrictStr]
208
- ingress: Optional[IngressConfig]
209
- user: Optional[RootUserConfig]
210
- node_selector: Optional[Dict[StrictStr, StrictStr]] = Field(alias="nodeSelector")
211
- tolerations: Optional[List[Union[k8s_schemas.V1Toleration, Dict]]]
212
- affinity: Optional[Union[k8s_schemas.V1Affinity, Dict]]
213
- labels: Optional[Dict[StrictStr, StrictStr]] = Field(alias="labels")
214
- annotations: Optional[Dict[StrictStr, StrictStr]] = Field(alias="annotations")
215
- priority_class_name: Optional[StrictStr] = Field(alias="priorityClassName")
199
+ deployment_version: Optional[StrictStr] = Field(
200
+ alias="deploymentVersion", default=None
201
+ )
202
+ release_name: Optional[StrictStr] = Field(alias="releaseName", default=None)
203
+ namespace: Optional[StrictStr] = Field(default=None)
204
+ rbac: Optional[RBACConfig] = None
205
+ polyaxon_secret: Optional[StrictStr] = Field(alias="polyaxonSecret", default=None)
206
+ internal_token: Optional[StrictStr] = Field(alias="internalToken", default=None)
207
+ password_length: Optional[StrictInt] = Field(alias="passwordLength", default=None)
208
+ password_auth: Optional[bool] = Field(alias="passwordAuth", default=None)
209
+ ssl: Optional[SSLConfig] = None
210
+ encryption_secret: Optional[StrictStr] = Field(
211
+ alias="encryptionSecret", default=None
212
+ )
213
+ platform_secret: Optional[StrictStr] = Field(alias="platformSecret", default=None)
214
+ agent_secret: Optional[StrictStr] = Field(alias="agentSecret", default=None)
215
+ timezone: Optional[StrictStr] = Field(default=None)
216
+ environment: Optional[StrictStr] = Field(default=None)
217
+ ingress: Optional[IngressConfig] = None
218
+ user: Optional[RootUserConfig] = None
219
+ node_selector: Optional[Dict[StrictStr, StrictStr]] = Field(
220
+ alias="nodeSelector", default=None
221
+ )
222
+ tolerations: Optional[List[Union[k8s_schemas.V1Toleration, Dict]]] = None
223
+ affinity: Optional[Union[k8s_schemas.V1Affinity, Dict]] = None
224
+ labels: Optional[Dict[StrictStr, StrictStr]] = Field(alias="labels", default=None)
225
+ annotations: Optional[Dict[StrictStr, StrictStr]] = Field(
226
+ alias="annotations", default=None
227
+ )
228
+ priority_class_name: Optional[StrictStr] = Field(
229
+ alias="priorityClassName", default=None
230
+ )
216
231
  celery_node_selector: Optional[Dict[StrictStr, StrictStr]] = Field(
217
- alias="celeryNodeSelector"
232
+ alias="celeryNodeSelector", default=None
218
233
  )
219
234
  celery_tolerations: Optional[List[Union[k8s_schemas.V1Toleration, Dict]]] = Field(
220
- alias="celeryTolerations"
235
+ alias="celeryTolerations", default=None
221
236
  )
222
237
  celery_affinity: Optional[Union[k8s_schemas.V1Affinity, Dict]] = Field(
223
- alias="celeryAffinity"
238
+ alias="celeryAffinity", default=None
239
+ )
240
+ limit_resources: Optional[bool] = Field(alias="limitResources", default=None)
241
+ global_replicas: Optional[StrictInt] = Field(alias="globalReplicas", default=None)
242
+ global_concurrency: Optional[StrictInt] = Field(
243
+ alias="globalConcurrency", default=None
244
+ )
245
+ gateway: Optional[ApiServiceConfig] = None
246
+ scheduler: Optional[WorkerServiceConfig] = None
247
+ compiler: Optional[WorkerServiceConfig] = None
248
+ worker: Optional[WorkerServiceConfig] = None
249
+ beat: Optional[DeploymentService] = None
250
+ agent: Optional[AgentServiceConfig] = None
251
+ operator: Optional[OperatorServiceConfig] = None
252
+ init: Optional[V1PolyaxonInitContainer] = None
253
+ sidecar: Optional[V1PolyaxonSidecarContainer] = None
254
+ notifier: Optional[V1PolyaxonNotifier] = None
255
+ cleaner: Optional[V1PolyaxonCleaner] = None
256
+ default_scheduling: Optional[V1DefaultScheduling] = Field(
257
+ alias="defaultScheduling", default=None
224
258
  )
225
- limit_resources: Optional[bool] = Field(alias="limitResources")
226
- global_replicas: Optional[StrictInt] = Field(alias="globalReplicas")
227
- global_concurrency: Optional[StrictInt] = Field(alias="globalConcurrency")
228
- gateway: Optional[ApiServiceConfig]
229
- scheduler: Optional[WorkerServiceConfig]
230
- compiler: Optional[WorkerServiceConfig]
231
- worker: Optional[WorkerServiceConfig]
232
- beat: Optional[DeploymentService]
233
- agent: Optional[AgentServiceConfig]
234
- operator: Optional[OperatorServiceConfig]
235
- init: Optional[V1PolyaxonInitContainer]
236
- sidecar: Optional[V1PolyaxonSidecarContainer]
237
- notifier: Optional[V1PolyaxonNotifier]
238
- cleaner: Optional[V1PolyaxonCleaner]
239
- default_scheduling: Optional[V1DefaultScheduling] = Field(alias="defaultScheduling")
240
259
  default_image_pull_secrets: Optional[List[StrictStr]] = Field(
241
- alias="defaultImagePullSecrets"
260
+ alias="defaultImagePullSecrets", default=None
261
+ )
262
+ clean_hooks: Optional[HooksConfig] = Field(alias="cleanHooks", default=None)
263
+ api_hooks: Optional[HooksConfig] = Field(alias="apiHooks", default=None)
264
+ flower: Optional[DeploymentService] = None
265
+ postgresql: Optional[PostgresqlConfig] = None
266
+ redis: Optional[RedisConfig] = None
267
+ rabbitmq: Optional[RabbitmqConfig] = None
268
+ broker: Optional[Literal["redis", "rabbitmq"]] = None
269
+ email: Optional[EmailConfig] = None
270
+ ldap: Optional[Dict] = None
271
+ metrics: Optional[Dict] = None
272
+ image_pull_secrets: Optional[List[StrictStr]] = Field(
273
+ alias="imagePullSecrets", default=None
274
+ )
275
+ host_name: Optional[StrictStr] = Field(alias="hostName", default=None)
276
+ allowed_hosts: Optional[List[StrictStr]] = Field(alias="allowedHosts", default=None)
277
+ include_host_ips: Optional[bool] = Field(alias="includeHostIps", default=None)
278
+ intervals: Optional[IntervalsConfig] = None
279
+ cleaning_intervals: Optional[Dict] = Field(alias="cleaningIntervals", default=None)
280
+ artifacts_store: Optional[V1Connection] = Field(
281
+ alias="artifactsStore", default=None
282
+ )
283
+ connections: Optional[List[V1Connection]] = Field(default=None)
284
+ mount_connections: Optional[List[str]] = Field(
285
+ alias="mountConnections", default=None
286
+ )
287
+ log_level: Optional[StrictStr] = Field(alias="logLevel", default=None)
288
+ security_context: Optional[SecurityContextConfig] = Field(
289
+ alias="securityContext", default=None
242
290
  )
243
- clean_hooks: Optional[HooksConfig] = Field(alias="cleanHooks")
244
- api_hooks: Optional[HooksConfig] = Field(alias="apiHooks")
245
- flower: Optional[DeploymentService]
246
- postgresql: Optional[PostgresqlConfig]
247
- redis: Optional[RedisConfig]
248
- rabbitmq: Optional[RabbitmqConfig]
249
- broker: Optional[Literal["redis", "rabbitmq"]]
250
- email: Optional[EmailConfig]
251
- ldap: Optional[Dict]
252
- metrics: Optional[Dict]
253
- image_pull_secrets: Optional[List[StrictStr]] = Field(alias="imagePullSecrets")
254
- host_name: Optional[StrictStr] = Field(alias="hostName")
255
- allowed_hosts: Optional[List[StrictStr]] = Field(alias="allowedHosts")
256
- include_host_ips: Optional[bool] = Field(alias="includeHostIps")
257
- intervals: Optional[IntervalsConfig]
258
- cleaning_intervals: Optional[Dict] = Field(alias="cleaningIntervals")
259
- artifacts_store: Optional[V1Connection] = Field(alias="artifactsStore")
260
- connections: Optional[List[V1Connection]]
261
- mount_connections: Optional[List[str]] = Field(alias="mountConnections")
262
- log_level: Optional[StrictStr] = Field(alias="logLevel")
263
- security_context: Optional[SecurityContextConfig] = Field(alias="securityContext")
264
291
  external_services: Optional[ExternalServicesConfig] = Field(
265
- alias="externalServices"
292
+ alias="externalServices", default=None
266
293
  )
267
- debug_mode: Optional[bool] = Field(alias="debugMode")
268
- organization_key: Optional[StrictStr] = Field(alias="organizationKey")
269
- auth: Optional[AuthConfig]
270
- proxy: Optional[ProxyConfig]
271
- ui: Optional[UIConfig]
272
- include_chart_revision: Optional[bool] = Field(alias="includeChartRevision")
273
- operators: Optional[OperatorsConfig]
274
- istio: Optional[Dict]
275
- dns: Optional[Dict]
276
-
277
- @root_validator
294
+ debug_mode: Optional[bool] = Field(alias="debugMode", default=None)
295
+ organization_key: Optional[StrictStr] = Field(alias="organizationKey", default=None)
296
+ auth: Optional[AuthConfig] = None
297
+ proxy: Optional[ProxyConfig] = None
298
+ ui: Optional[UIConfig] = None
299
+ include_chart_revision: Optional[bool] = Field(
300
+ alias="includeChartRevision", default=None
301
+ )
302
+ operators: Optional[OperatorsConfig] = None
303
+ istio: Optional[Dict] = None
304
+ dns: Optional[Dict] = None
305
+
306
+ @model_validator(**validation_after)
278
307
  def validate_deployment(cls, values):
279
308
  validate_deployment_chart(
280
- deployment_chart=values.get("deployment_chart"),
281
- agent=values.get("agent"),
282
- environment=values.get("environment"),
309
+ deployment_chart=cls.get_value_for_key("deployment_chart", values),
310
+ agent=cls.get_value_for_key("agent", values),
311
+ environment=cls.get_value_for_key("environment", values),
283
312
  )
284
313
  validate_platform_deployment(
285
- postgresql=values.get("postgresql"),
286
- redis=values.get("redis"),
287
- rabbitmq=values.get("rabbitmq"),
288
- broker=values.get("broker"),
289
- scheduler=values.get("scheduler"),
290
- compiler=values.get("compiler"),
291
- worker=values.get("worker"),
292
- beat=values.get("beat"),
293
- external_services=values.get("external_services"),
314
+ postgresql=cls.get_value_for_key("postgresql", values),
315
+ redis=cls.get_value_for_key("redis", values),
316
+ rabbitmq=cls.get_value_for_key("rabbitmq", values),
317
+ broker=cls.get_value_for_key("broker", values),
318
+ scheduler=cls.get_value_for_key("scheduler", values),
319
+ compiler=cls.get_value_for_key("compiler", values),
320
+ worker=cls.get_value_for_key("worker", values),
321
+ beat=cls.get_value_for_key("beat", values),
322
+ external_services=cls.get_value_for_key("external_services", values),
294
323
  )
295
- if values.get("deployment_chart") == DeploymentCharts.AGENT:
324
+ if cls.get_value_for_key("deployment_chart", values) == DeploymentCharts.AGENT:
296
325
  wrong_agent_deployment_keys(
297
- password_length=values.get("password_length"),
298
- password_auth=values.get("password_auth"),
299
- platform_secret=values.get("platform_secret"),
300
- encryption_secret=values.get("encryption_secret"),
301
- user=values.get("user"),
302
- global_replicas=values.get("global_replicas"),
303
- global_concurrency=values.get("global_concurrency"),
304
- scheduler=values.get("scheduler"),
305
- compiler=values.get("compiler"),
306
- worker=values.get("worker"),
307
- beat=values.get("beat"),
308
- clean_hook=values.get("clean_hook"),
309
- api_hooks=values.get("api_hooks"),
310
- flower=values.get("flower"),
311
- postgresql=values.get("postgresql"),
312
- redis=values.get("redis"),
313
- rabbitmq=values.get("rabbitmq"),
314
- broker=values.get("broker"),
315
- email=values.get("email"),
316
- ldap=values.get("ldap"),
317
- intervals=values.get("intervals"),
318
- metrics=values.get("metrics"),
319
- organization_key=values.get("organization_key"),
320
- ui=values.get("ui"),
326
+ password_length=cls.get_value_for_key("password_length", values),
327
+ password_auth=cls.get_value_for_key("password_auth", values),
328
+ platform_secret=cls.get_value_for_key("platform_secret", values),
329
+ encryption_secret=cls.get_value_for_key("encryption_secret", values),
330
+ user=cls.get_value_for_key("user", values),
331
+ global_replicas=cls.get_value_for_key("global_replicas", values),
332
+ global_concurrency=cls.get_value_for_key("global_concurrency", values),
333
+ scheduler=cls.get_value_for_key("scheduler", values),
334
+ compiler=cls.get_value_for_key("compiler", values),
335
+ worker=cls.get_value_for_key("worker", values),
336
+ beat=cls.get_value_for_key("beat", values),
337
+ clean_hook=cls.get_value_for_key("clean_hook", values),
338
+ api_hooks=cls.get_value_for_key("api_hooks", values),
339
+ flower=cls.get_value_for_key("flower", values),
340
+ postgresql=cls.get_value_for_key("postgresql", values),
341
+ redis=cls.get_value_for_key("redis", values),
342
+ rabbitmq=cls.get_value_for_key("rabbitmq", values),
343
+ broker=cls.get_value_for_key("broker", values),
344
+ email=cls.get_value_for_key("email", values),
345
+ ldap=cls.get_value_for_key("ldap", values),
346
+ intervals=cls.get_value_for_key("intervals", values),
347
+ metrics=cls.get_value_for_key("metrics", values),
348
+ organization_key=cls.get_value_for_key("organization_key", values),
321
349
  )
322
350
 
323
351
  return values
324
352
 
325
- @validator("affinity", "celery_affinity", always=True, pre=True)
353
+ @field_validator(
354
+ "affinity", "celery_affinity", **validation_always, **validation_before
355
+ )
326
356
  def validate_affinity(cls, v):
327
357
  return k8s_validation.validate_k8s_affinity(v)
328
358
 
329
- @validator("tolerations", "celery_tolerations", always=True, pre=True)
359
+ @field_validator(
360
+ "tolerations", "celery_tolerations", **validation_always, **validation_before
361
+ )
330
362
  def validate_tolerations(cls, v):
331
363
  if not v:
332
364
  return v