polyaxon 2.1.8__py3-none-any.whl → 2.2.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 (57) 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 +42 -23
  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/_utils/fqn_utils.py +25 -2
  51. polyaxon/pkg.py +1 -1
  52. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.dist-info}/METADATA +2 -2
  53. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.dist-info}/RECORD +57 -40
  54. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.dist-info}/LICENSE +0 -0
  55. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.dist-info}/WHEEL +0 -0
  56. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.dist-info}/entry_points.txt +0 -0
  57. {polyaxon-2.1.8.dist-info → polyaxon-2.2.0.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,11 @@ from clipped.utils.versions import compare_versions
21
21
  from urllib3.exceptions import HTTPError
22
22
 
23
23
  from polyaxon import settings
24
- from polyaxon._cli.dashboard import get_dashboard, get_dashboard_url
24
+ from polyaxon._cli.dashboard import (
25
+ get_dashboard,
26
+ get_dashboard_url,
27
+ get_project_subpath_url,
28
+ )
25
29
  from polyaxon._cli.errors import handle_cli_error, is_in_ce
26
30
  from polyaxon._cli.options import (
27
31
  OPTIONS_NAME,
@@ -47,7 +51,7 @@ from polyaxon.api import (
47
51
  REWRITE_SERVICES_V1,
48
52
  SERVICES_V1,
49
53
  )
50
- from polyaxon.client import RunClient, V1Run, get_run_logs
54
+ from polyaxon.client import RunClient, V1Run, V1RunSettings, get_run_logs
51
55
  from polyaxon.exceptions import (
52
56
  ApiException,
53
57
  PolyaxonClientException,
@@ -82,6 +86,14 @@ DEFAULT_EXCLUDE = [
82
86
  ]
83
87
 
84
88
 
89
+ def get_op_agent_host(runSettings: V1RunSettings):
90
+ host_kwargs = {}
91
+ if runSettings and runSettings.agent and runSettings.agent.url:
92
+ host_kwargs["host"] = runSettings.agent.url
93
+
94
+ return host_kwargs
95
+
96
+
85
97
  def handle_run_statuses(status, conditions, table):
86
98
  if not conditions:
87
99
  return False
@@ -286,7 +298,7 @@ def ls(
286
298
  else:
287
299
  Printer.warning(f"Skipping run {uid}, offline data not found.")
288
300
  else:
289
- owner, project_name = get_project_or_local(
301
+ owner, _, project_name = get_project_or_local(
290
302
  project or ctx.obj.get("project"), is_cli=True
291
303
  )
292
304
 
@@ -431,7 +443,7 @@ def get(ctx, project, uid, offline, path, output):
431
443
  sys.exit(1)
432
444
  run_data = RunConfigManager.read_from_path(offline_path)
433
445
  else:
434
- owner, project_name, run_uuid = get_project_run_or_local(
446
+ owner, team, project_name, run_uuid = get_project_run_or_local(
435
447
  project or ctx.obj.get("project"),
436
448
  uid,
437
449
  is_cli=True,
@@ -456,7 +468,9 @@ def get(ctx, project, uid, offline, path, output):
456
468
  )
457
469
  if output:
458
470
  run_url = get_dashboard_url(
459
- subpath="{}/{}/runs/{}".format(owner, project_name, run_uuid)
471
+ subpath="{}/runs/{}".format(
472
+ get_project_subpath_url(owner, team, project_name), run_uuid
473
+ )
460
474
  )
461
475
  config["url"] = run_url
462
476
  handle_output(config, output)
@@ -529,7 +543,7 @@ def delete(ctx, project, uid, yes, offline, path):
529
543
  return
530
544
 
531
545
  # Resume normal flow
532
- owner, project_name, run_uuid = get_project_run_or_local(
546
+ owner, _, project_name, run_uuid = get_project_run_or_local(
533
547
  project or ctx.obj.get("project"),
534
548
  uid or ctx.obj.get("run_uuid"),
535
549
  is_cli=True,
@@ -624,7 +638,7 @@ def update(ctx, project, uid, name, description, tags, offline, path):
624
638
  )
625
639
  sys.exit(1)
626
640
  else:
627
- owner, project_name, run_uuid = get_project_run_or_local(
641
+ owner, _, project_name, run_uuid = get_project_run_or_local(
628
642
  project or ctx.obj.get("project"),
629
643
  uid or ctx.obj.get("run_uuid"),
630
644
  is_cli=True,
@@ -663,7 +677,7 @@ def approve(ctx, project, uid):
663
677
  \b
664
678
  $ polyaxon ops approve --uid 8aac02e3a62a4f0aaa257c59da5eab80
665
679
  """
666
- owner, project_name, run_uuid = get_project_run_or_local(
680
+ owner, _, project_name, run_uuid = get_project_run_or_local(
667
681
  project or ctx.obj.get("project"),
668
682
  uid or ctx.obj.get("run_uuid"),
669
683
  is_cli=True,
@@ -710,7 +724,7 @@ def stop(ctx, project, uid, yes):
710
724
  \b
711
725
  $ polyaxon ops stop --uid 8aac02e3a62a4f0aaa257c59da5eab80
712
726
  """
713
- owner, project_name, run_uuid = get_project_run_or_local(
727
+ owner, _, project_name, run_uuid = get_project_run_or_local(
714
728
  project or ctx.obj.get("project"),
715
729
  uid or ctx.obj.get("run_uuid"),
716
730
  is_cli=True,
@@ -762,7 +776,7 @@ def skip(ctx, project, uid, yes):
762
776
  \b
763
777
  $ polyaxon ops skip --uid 8aac02e3a62a4f0aaa257c59da5eab80
764
778
  """
765
- owner, project_name, run_uuid = get_project_run_or_local(
779
+ owner, _, project_name, run_uuid = get_project_run_or_local(
766
780
  project or ctx.obj.get("project"),
767
781
  uid or ctx.obj.get("run_uuid"),
768
782
  is_cli=True,
@@ -866,7 +880,7 @@ def restart(
866
880
  if polyaxonfile:
867
881
  content = OperationSpecification.read(polyaxonfile, is_preset=True).to_json()
868
882
 
869
- owner, project_name, run_uuid = get_project_run_or_local(
883
+ owner, _, project_name, run_uuid = get_project_run_or_local(
870
884
  project or ctx.obj.get("project"),
871
885
  uid or ctx.obj.get("run_uuid"),
872
886
  is_cli=True,
@@ -951,7 +965,7 @@ def resume(
951
965
  if polyaxonfile:
952
966
  content = OperationSpecification.read(polyaxonfile, is_preset=True).to_json()
953
967
 
954
- owner, project_name, run_uuid = get_project_run_or_local(
968
+ owner, _, project_name, run_uuid = get_project_run_or_local(
955
969
  project or ctx.obj.get("project"),
956
970
  uid or ctx.obj.get("run_uuid"),
957
971
  is_cli=True,
@@ -994,7 +1008,7 @@ def invalidate(ctx, project, uid):
994
1008
  \b
995
1009
  $ polyaxon ops invalidate --uid 8aac02e3a62a4f0aaa257c59da5eab80
996
1010
  """
997
- owner, project_name, run_uuid = get_project_run_or_local(
1011
+ owner, _, project_name, run_uuid = get_project_run_or_local(
998
1012
  project or ctx.obj.get("project"),
999
1013
  uid or ctx.obj.get("run_uuid"),
1000
1014
  is_cli=True,
@@ -1020,7 +1034,7 @@ def invalidate(ctx, project, uid):
1020
1034
  "--executor",
1021
1035
  "-exc",
1022
1036
  type=str,
1023
- help="The local executor to use, possible values are: docker, k8s, process.",
1037
+ help="The executor to use, possible values are: docker, k8s, process.",
1024
1038
  )
1025
1039
  @click.pass_context
1026
1040
  @clean_outputs
@@ -1129,7 +1143,7 @@ def execute(ctx, project, uid, executor):
1129
1143
  executor.create_from_run(response, default_auth=not is_in_ce())
1130
1144
 
1131
1145
  def _execute_on_local_process(response: V1Run, run_client: RunClient):
1132
- from polyaxon.process.executor.executor import Executor
1146
+ from polyaxon._local_process.executor import Executor
1133
1147
 
1134
1148
  run_client.log_status(
1135
1149
  V1Statuses.STARTING,
@@ -1138,27 +1152,52 @@ def execute(ctx, project, uid, executor):
1138
1152
  )
1139
1153
  executor = Executor()
1140
1154
  if not executor.manager.check():
1141
- raise Printer.error("Conda is required to run this command.", sys_exit=True)
1142
-
1143
- # def _check_conda():
1144
- # from polyaxon._deploy.operators.conda import CondaOperator
1145
- #
1146
- # conda = CondaOperator()
1147
- # if not conda.check():
1148
- # raise Printer.error("Conda is required to run this command.", sys_exit=True)
1149
- #
1150
- # envs = conda.execute(["env", "list", "--json"], is_json=True)
1151
- # env_names = [os.path.basename(env) for env in envs["envs"]]
1152
- # if conda_env not in env_names:
1153
- # raise Printer.error(
1154
- # "Conda env `{}` is not installed.".format(conda_env), sys_exit=True
1155
- # )
1156
- #
1157
- # cmd_bash, cmd_args = specification.run.get_container_cmd()
1158
- # cmd_args = ["source activate {}".format(conda_env)] + cmd_args
1159
- # subprocess.Popen(cmd_bash + [" && ".join(cmd_args)], close_fds=True)
1160
-
1161
- owner, project_name, run_uuid = get_project_run_or_local(
1155
+ run_client.log_failed(
1156
+ reason="CliProcessExecutor",
1157
+ message="Local process can't be used to run this operation.",
1158
+ )
1159
+ raise Printer.error(
1160
+ "Local process can't be used to run this operation.", sys_exit=True
1161
+ )
1162
+
1163
+ run_client.log_status(
1164
+ V1Statuses.RUNNING,
1165
+ reason="CliProcessExecutor",
1166
+ message="Operation is running",
1167
+ )
1168
+
1169
+ if V1RunKind.has_pipeline(response.kind):
1170
+ has_children = True
1171
+ while has_children:
1172
+ pipeline_runs = run_client.list_children(
1173
+ query="status:created", sort="created_at", limit=1
1174
+ )
1175
+ if pipeline_runs.results:
1176
+ current_run_client = RunClient(
1177
+ owner=owner,
1178
+ project=project_name,
1179
+ run_uuid=pipeline_runs.results[0].uuid,
1180
+ manual_exceptions_handling=True,
1181
+ )
1182
+ current_run_client.refresh_data()
1183
+ _prepare(current_run_client.run_data, current_run_client)
1184
+ _execute(current_run_client.run_data, current_run_client)
1185
+ else:
1186
+ has_children = False
1187
+ return
1188
+ else:
1189
+ result = executor.create_from_run(response, default_auth=not is_in_ce())
1190
+ if result["status"] == V1Statuses.SUCCEEDED:
1191
+ run_client.log_succeeded(
1192
+ reason="CliProcessExecutor", message="Operation was succeeded"
1193
+ )
1194
+ else:
1195
+ run_client.log_failed(
1196
+ reason="CliProcessExecutor",
1197
+ message="Operation failed.\n{}".format(result["message"]),
1198
+ )
1199
+
1200
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1162
1201
  project or ctx.obj.get("project"),
1163
1202
  uid or ctx.obj.get("run_uuid"),
1164
1203
  is_cli=True,
@@ -1282,7 +1321,7 @@ def statuses(ctx, project, uid, watch, offline, path):
1282
1321
  sys.exit(1)
1283
1322
  return
1284
1323
 
1285
- owner, project_name, run_uuid = get_project_run_or_local(
1324
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1286
1325
  project or ctx.obj.get("project"),
1287
1326
  uid or ctx.obj.get("run_uuid"),
1288
1327
  is_cli=True,
@@ -1350,7 +1389,7 @@ def statuses(ctx, project, uid, watch, offline, path):
1350
1389
  # )
1351
1390
  # sys.exit(1)
1352
1391
  #
1353
- # owner, project_name, run_uuid = get_project_run_or_local(
1392
+ # owner, team, project_name, run_uuid = get_project_run_or_local(
1354
1393
  # ctx.obj.get("project"), ctx.obj.get("run_uuid"), is_cli=True,
1355
1394
  # )
1356
1395
  #
@@ -1442,7 +1481,7 @@ def logs(ctx, project, uid, follow, hide_time, all_containers, all_info, offline
1442
1481
  sys.exit(1)
1443
1482
  return
1444
1483
 
1445
- owner, project_name, run_uuid = get_project_run_or_local(
1484
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1446
1485
  project or ctx.obj.get("project"),
1447
1486
  uid or ctx.obj.get("run_uuid"),
1448
1487
  is_cli=True,
@@ -1488,7 +1527,7 @@ def inspect(ctx, project, uid):
1488
1527
  \b
1489
1528
  $ polyaxon ops inspect -p acme/project -uid 8aac02e3a62a4f0aaa257c59da5eab80
1490
1529
  """
1491
- owner, project_name, run_uuid = get_project_run_or_local(
1530
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1492
1531
  project or ctx.obj.get("project"),
1493
1532
  uid or ctx.obj.get("run_uuid"),
1494
1533
  is_cli=True,
@@ -1547,7 +1586,7 @@ def shell(ctx, project, uid, command, pod, container):
1547
1586
  """
1548
1587
  from polyaxon._vendor.shell_pty import PseudoTerminal
1549
1588
 
1550
- owner, project_name, run_uuid = get_project_run_or_local(
1589
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1551
1590
  project or ctx.obj.get("project"),
1552
1591
  uid or ctx.obj.get("run_uuid"),
1553
1592
  is_cli=True,
@@ -1652,7 +1691,7 @@ def artifacts(
1652
1691
  \b
1653
1692
  $ polyaxon ops artifacts -uid 8aac02e3a62a4f0aaa257c59da5eab80 -l-kind model -l-kind env --path="this/path"
1654
1693
  """
1655
- owner, project_name, run_uuid = get_project_run_or_local(
1694
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1656
1695
  project or ctx.obj.get("project"),
1657
1696
  uid or ctx.obj.get("run_uuid"),
1658
1697
  is_cli=True,
@@ -1830,7 +1869,7 @@ def upload(ctx, project, uid, path_from, path_to, sync_failure):
1830
1869
  \b
1831
1870
  $ polyaxon ops upload -uid 8aac02e3a62a4f0aaa257c59da5eab80 --path-to="path/to/upload/to"
1832
1871
  """
1833
- owner, project_name, run_uuid = get_project_run_or_local(
1872
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1834
1873
  project or ctx.obj.get("project"),
1835
1874
  uid or ctx.obj.get("run_uuid"),
1836
1875
  is_cli=True,
@@ -1904,7 +1943,7 @@ def transfer(ctx, project, uid, to_project):
1904
1943
  \b
1905
1944
  $ polyaxon ops transfer -p acme/foobar -uid 8aac02e3a62a4f0aaa257c59da5eab80 -to=dest-project
1906
1945
  """
1907
- owner, project_name, run_uuid = get_project_run_or_local(
1946
+ owner, _, project_name, run_uuid = get_project_run_or_local(
1908
1947
  project or ctx.obj.get("project"),
1909
1948
  uid or ctx.obj.get("run_uuid"),
1910
1949
  is_cli=True,
@@ -1972,13 +2011,16 @@ def dashboard(ctx, project, uid, yes, url, offline, path, server_config):
1972
2011
  sys.exit(1)
1973
2012
  run_data = RunConfigManager.read_from_path(offline_path)
1974
2013
  owner, project_name, run_uuid = run_data.owner, run_data.project, run_data.uuid
2014
+ team = None
1975
2015
  else:
1976
- owner, project_name, run_uuid = get_project_run_or_local(
2016
+ owner, team, project_name, run_uuid = get_project_run_or_local(
1977
2017
  project or ctx.obj.get("project"),
1978
2018
  uid or ctx.obj.get("run_uuid"),
1979
2019
  is_cli=True,
1980
2020
  )
1981
- subpath = "{}/{}/runs/{}".format(owner, project_name, run_uuid)
2021
+ subpath = "{}/runs/{}".format(
2022
+ get_project_subpath_url(owner, team, project_name), run_uuid
2023
+ )
1982
2024
  dashboard_url = get_dashboard_url(subpath=subpath)
1983
2025
  get_dashboard(dashboard_url=dashboard_url, url_only=url, yes=yes)
1984
2026
  if offline:
@@ -2022,7 +2064,7 @@ def service(ctx, project, uid, yes, external, url):
2022
2064
  You can open the service embedded in Polyaxon UI or using the real service URL,
2023
2065
  please use the `--external` flag.
2024
2066
  """
2025
- owner, project_name, run_uuid = get_project_run_or_local(
2067
+ owner, team, project_name, run_uuid = get_project_run_or_local(
2026
2068
  project or ctx.obj.get("project"),
2027
2069
  uid or ctx.obj.get("run_uuid"),
2028
2070
  is_cli=True,
@@ -2055,8 +2097,12 @@ def service(ctx, project, uid, yes, external, url):
2055
2097
 
2056
2098
  wait_for_running_condition(client)
2057
2099
 
2100
+ host_kwargs = get_op_agent_host(client.settings)
2058
2101
  run_url = get_dashboard_url(
2059
- subpath="{}/{}/runs/{}/service".format(owner, project_name, run_uuid)
2102
+ subpath="{}/runs/{}/service".format(
2103
+ get_project_subpath_url(owner, team, project_name), run_uuid
2104
+ ),
2105
+ **host_kwargs,
2060
2106
  )
2061
2107
 
2062
2108
  namespace = client.run_data.settings.namespace
@@ -2066,8 +2112,8 @@ def service(ctx, project, uid, yes, external, url):
2066
2112
  if rewrite_path:
2067
2113
  service_endpoint = REWRITE_EXTERNAL_V1 if is_external else REWRITE_SERVICES_V1
2068
2114
 
2069
- service_subpath = "{}/{}/{}/runs/{}/".format(
2070
- namespace, owner, project_name, run_uuid
2115
+ service_subpath = "{}/{}/runs/{}/".format(
2116
+ get_project_subpath_url(namespace, team, owner), project_name, run_uuid
2071
2117
  )
2072
2118
  port = 80
2073
2119
  if client.settings and client.settings.agent:
@@ -2080,9 +2126,9 @@ def service(ctx, project, uid, yes, external, url):
2080
2126
  if port:
2081
2127
  service_subpath = "{}{}/".format(service_subpath, port)
2082
2128
 
2129
+ host_kwargs = get_op_agent_host(client.settings)
2083
2130
  external_run_url = get_dashboard_url(
2084
- base=service_endpoint,
2085
- subpath=service_subpath,
2131
+ base=service_endpoint, subpath=service_subpath, **host_kwargs
2086
2132
  )
2087
2133
 
2088
2134
  if url:
@@ -2163,7 +2209,7 @@ def pull(
2163
2209
  \b
2164
2210
  $ polyaxon ops pull -a
2165
2211
  """
2166
- owner, project_name = get_project_or_local(
2212
+ owner, _, project_name = get_project_or_local(
2167
2213
  project or ctx.obj.get("project"), is_cli=True
2168
2214
  )
2169
2215
 
@@ -2283,7 +2329,7 @@ def push(ctx, project, uid, all_runs, no_artifacts, clean, path, reset_project):
2283
2329
  \b
2284
2330
  $ polyaxon ops push -uid 8aac02e3a62a4f0aaa257c59da5eab80 --reset-project -p send-to-project
2285
2331
  """
2286
- owner, project_name = get_project_or_local(
2332
+ owner, _, project_name = get_project_or_local(
2287
2333
  project or ctx.obj.get("project"), is_cli=True
2288
2334
  )
2289
2335
 
@@ -12,7 +12,7 @@ from clipped.utils.responses import get_meta_response
12
12
  from clipped.utils.validation import validate_tags
13
13
  from urllib3.exceptions import HTTPError
14
14
 
15
- from polyaxon._cli.dashboard import get_dashboard_url
15
+ from polyaxon._cli.dashboard import get_dashboard_url, get_project_subpath_url
16
16
  from polyaxon._cli.errors import handle_cli_error
17
17
  from polyaxon._contexts.paths import get_offline_base_path
18
18
  from polyaxon._schemas.lifecycle import V1ProjectVersionKind
@@ -170,6 +170,7 @@ def list_project_versions(
170
170
 
171
171
  def register_project_version(
172
172
  owner: str,
173
+ team: Optional[str],
173
174
  project_name: str,
174
175
  version: str,
175
176
  kind: V1ProjectVersionKind,
@@ -209,7 +210,9 @@ def register_project_version(
209
210
  Printer.print(
210
211
  "You can view this version on Polyaxon UI: {}".format(
211
212
  get_dashboard_url(
212
- subpath="{}/{}/{}s/{}".format(owner, project_name, kind, version)
213
+ subpath="{}/{}s/{}".format(
214
+ get_project_subpath_url(owner, team, project_name), kind, version
215
+ )
213
216
  )
214
217
  )
215
218
  )
@@ -217,6 +220,7 @@ def register_project_version(
217
220
 
218
221
  def copy_project_version(
219
222
  owner: str,
223
+ team: Optional[str],
220
224
  project_name: str,
221
225
  version: str,
222
226
  kind: V1ProjectVersionKind,
@@ -261,8 +265,10 @@ def copy_project_version(
261
265
  Printer.print(
262
266
  "You can view this version on Polyaxon UI: {}".format(
263
267
  get_dashboard_url(
264
- subpath="{}/{}/{}s/{}".format(
265
- owner, to_project or project_name, kind, _version.name
268
+ subpath="{}/{}s/{}".format(
269
+ get_project_subpath_url(owner, team, to_project or project_name),
270
+ kind,
271
+ _version.name,
266
272
  )
267
273
  )
268
274
  )
@@ -271,6 +277,7 @@ def copy_project_version(
271
277
 
272
278
  def get_project_version(
273
279
  owner: str,
280
+ team: Optional[str],
274
281
  project_name: str,
275
282
  kind: V1ProjectVersionKind,
276
283
  version: str,
@@ -288,6 +295,17 @@ def get_project_version(
288
295
  try:
289
296
  response = polyaxon_client.get_version(kind, version)
290
297
  get_version_details(response, content_callback)
298
+ Printer.print(
299
+ "You can view this version on Polyaxon UI: {}".format(
300
+ get_dashboard_url(
301
+ subpath="{}/{}s/{}".format(
302
+ get_project_subpath_url(owner, team, project_name),
303
+ kind,
304
+ version,
305
+ )
306
+ )
307
+ )
308
+ )
291
309
  except (ApiException, HTTPError) as e:
292
310
  handle_cli_error(
293
311
  e,
@@ -470,13 +488,16 @@ def stage_project_version(
470
488
 
471
489
  def open_project_version_dashboard(
472
490
  owner: str,
491
+ team: Optional[str],
473
492
  project_name: str,
474
493
  kind: V1ProjectVersionKind,
475
494
  version: str,
476
495
  url: str,
477
496
  yes: bool = False,
478
497
  ):
479
- subpath = "{}/{}/{}s/{}".format(owner, project_name, kind, version)
498
+ subpath = "{}/{}s/{}".format(
499
+ get_project_subpath_url(owner, team, project_name), kind, version
500
+ )
480
501
 
481
502
  artifact_url = get_dashboard_url(subpath=subpath)
482
503
  if url:
polyaxon/_cli/projects.py CHANGED
@@ -8,7 +8,7 @@ from clipped.utils.responses import get_meta_response
8
8
  from clipped.utils.validation import validate_tags
9
9
  from urllib3.exceptions import HTTPError
10
10
 
11
- from polyaxon._cli.dashboard import get_dashboard_url
11
+ from polyaxon._cli.dashboard import get_dashboard_url, get_project_subpath_url
12
12
  from polyaxon._cli.errors import handle_cli_error
13
13
  from polyaxon._cli.init import init as init_project
14
14
  from polyaxon._cli.options import OPTIONS_NAME, OPTIONS_OWNER, OPTIONS_PROJECT
@@ -19,6 +19,7 @@ from polyaxon._env_vars.getters.user import get_local_owner
19
19
  from polyaxon._managers.project import ProjectConfigManager
20
20
  from polyaxon._utils import cache
21
21
  from polyaxon._utils.cache import get_local_project
22
+ from polyaxon._utils.fqn_utils import get_owner_team_space
22
23
  from polyaxon.client import ProjectClient, V1Project
23
24
  from polyaxon.exceptions import ApiException
24
25
  from polyaxon.logger import clean_outputs
@@ -74,7 +75,7 @@ def create(ctx, name, description, tags, public, init):
74
75
  command_help="project create",
75
76
  sys_exit=True,
76
77
  )
77
- owner, project_name = resolve_entity_info(
78
+ owner, team, project_name = resolve_entity_info(
78
79
  name or ctx.obj.get("project"), is_cli=True, entity_name="project"
79
80
  )
80
81
 
@@ -90,7 +91,9 @@ def create(ctx, name, description, tags, public, init):
90
91
  project_config = V1Project(
91
92
  name=project_name, description=description, tags=tags, is_public=public
92
93
  )
93
- polyaxon_client = ProjectClient(owner=owner, manual_exceptions_handling=True)
94
+ polyaxon_client = ProjectClient(
95
+ owner=get_owner_team_space(owner, team), manual_exceptions_handling=True
96
+ )
94
97
  _project = polyaxon_client.create(project_config)
95
98
  config = polyaxon_client.client.sanitize_for_serialization(_project)
96
99
  cache.cache(config_manager=ProjectConfigManager, config=config)
@@ -103,7 +106,9 @@ def create(ctx, name, description, tags, public, init):
103
106
  Printer.success("Project `{}` was created successfully.".format(_project.name))
104
107
  Printer.print(
105
108
  "You can view this project on Polyaxon UI: {}".format(
106
- get_dashboard_url(subpath="{}/{}".format(owner, _project.name))
109
+ get_dashboard_url(
110
+ subpath=get_project_subpath_url(owner, team, _project.name)
111
+ )
107
112
  )
108
113
  )
109
114
 
@@ -195,7 +200,7 @@ def get(ctx, _project):
195
200
  \b
196
201
  $ polyaxon project get -p owner/project
197
202
  """
198
- owner, project_name = get_project_or_local(
203
+ owner, team, project_name = get_project_or_local(
199
204
  _project or ctx.obj.get("project"), is_cli=True
200
205
  )
201
206
 
@@ -214,6 +219,13 @@ def get(ctx, _project):
214
219
  project=project_name,
215
220
  )
216
221
  get_entity_details(polyaxon_client.project_data, "Project")
222
+ Printer.print(
223
+ "You can view this project on Polyaxon UI: {}".format(
224
+ get_dashboard_url(
225
+ subpath=get_project_subpath_url(owner, team, project_name)
226
+ )
227
+ )
228
+ )
217
229
  except (ApiException, HTTPError) as e:
218
230
  handle_cli_error(
219
231
  e, message="Could not get project `{}`.".format(project_name), sys_exit=True
@@ -237,7 +249,7 @@ def delete(ctx, _project, yes):
237
249
 
238
250
  Uses /docs/core/cli/#caching
239
251
  """
240
- owner, project_name = get_project_or_local(
252
+ owner, _, project_name = get_project_or_local(
241
253
  _project or ctx.obj.get("project"), is_cli=True
242
254
  )
243
255
 
@@ -300,7 +312,7 @@ def update(ctx, _project, name, description, tags, private):
300
312
  \b
301
313
  $ polyaxon update --tags="foo, bar"
302
314
  """
303
- owner, project_name = get_project_or_local(
315
+ owner, _, project_name = get_project_or_local(
304
316
  _project or ctx.obj.get("project"), is_cli=True
305
317
  )
306
318
 
@@ -357,10 +369,12 @@ def update(ctx, _project, name, description, tags, private):
357
369
  @clean_outputs
358
370
  def dashboard(ctx, _project, yes, url):
359
371
  """Open this project's dashboard details in browser."""
360
- owner, project_name = get_project_or_local(
372
+ owner, team, project_name = get_project_or_local(
361
373
  _project or ctx.obj.get("project"), is_cli=True
362
374
  )
363
- project_url = get_dashboard_url(subpath="{}/{}".format(owner, project_name))
375
+ project_url = get_dashboard_url(
376
+ subpath=get_project_subpath_url(owner, team, project_name)
377
+ )
364
378
  if url:
365
379
  Printer.header("The dashboard is available at: {}".format(project_url))
366
380
  sys.exit(0)
polyaxon/_cli/run.py CHANGED
@@ -10,10 +10,11 @@ from clipped.utils import git as git_utils
10
10
  from clipped.utils.validation import validate_tags
11
11
  from urllib3.exceptions import HTTPError
12
12
 
13
- from polyaxon._cli.dashboard import get_dashboard_url
13
+ from polyaxon._cli.dashboard import get_dashboard_url, get_project_subpath_url
14
14
  from polyaxon._cli.errors import handle_cli_error
15
15
  from polyaxon._cli.operations import approve
16
16
  from polyaxon._cli.operations import execute as run_execute
17
+ from polyaxon._cli.operations import get_op_agent_host
17
18
  from polyaxon._cli.operations import logs as run_logs
18
19
  from polyaxon._cli.operations import shell as run_shell
19
20
  from polyaxon._cli.operations import statuses
@@ -30,6 +31,7 @@ from polyaxon._polyaxonfile import check_polyaxonfile
30
31
  from polyaxon._runner.kinds import RunnerKind
31
32
  from polyaxon._schemas.lifecycle import ManagedBy
32
33
  from polyaxon._utils import cache
34
+ from polyaxon._utils.fqn_utils import get_owner_team_space
33
35
  from polyaxon.client import RunClient
34
36
  from polyaxon.exceptions import ApiException
35
37
  from polyaxon.logger import clean_outputs
@@ -43,6 +45,7 @@ def _run(
43
45
  ctx,
44
46
  name: str,
45
47
  owner: str,
48
+ team: Optional[str],
46
49
  project_name: str,
47
50
  description: str,
48
51
  tags: List[str],
@@ -61,11 +64,14 @@ def _run(
61
64
  owner=owner, project=project_name, manual_exceptions_handling=True
62
65
  )
63
66
 
67
+ owner_team = get_owner_team_space(owner, team)
68
+ project_url = get_project_subpath_url(owner, team, project_name)
69
+
64
70
  def get_instance_info(r):
65
71
  rn = (
66
72
  f"[white]{r.name}[/white]@[white]{r.uuid}[/white]"
67
73
  if r.name
68
- else "[white]{r.uuid}[/white]"
74
+ else f"[white]{r.uuid}[/white]"
69
75
  )
70
76
  return f"[white]{owner}[/white]/[white]{project_name}[/white]:{rn}"
71
77
 
@@ -93,8 +99,9 @@ def _run(
93
99
  meta_info=meta_info,
94
100
  pending=pending,
95
101
  )
102
+ host_kwargs = get_op_agent_host(response.settings)
96
103
  run_url = get_dashboard_url(
97
- subpath="{}/{}/runs/{}".format(owner, project_name, response.uuid)
104
+ subpath="{}/runs/{}".format(project_url, response.uuid), **host_kwargs
98
105
  )
99
106
  if output:
100
107
  response_data = polyaxon_client.client.sanitize_for_serialization(
@@ -125,26 +132,38 @@ def _run(
125
132
 
126
133
  def execute_run_locally(run_uuid: str):
127
134
  ctx.obj = {
128
- "project": "{}/{}".format(owner, project_name),
135
+ "project": "{}/{}".format(owner_team, project_name),
129
136
  "run_uuid": run_uuid,
130
137
  "executor": executor,
131
138
  }
132
139
  ctx.invoke(run_execute)
133
140
 
134
141
  def watch_run_statuses(run_uuid: str):
135
- ctx.obj = {"project": "{}/{}".format(owner, project_name), "run_uuid": run_uuid}
142
+ ctx.obj = {
143
+ "project": "{}/{}".format(owner_team, project_name),
144
+ "run_uuid": run_uuid,
145
+ }
136
146
  ctx.invoke(statuses, watch=True)
137
147
 
138
148
  def watch_run_logs(run_uuid: str):
139
- ctx.obj = {"project": "{}/{}".format(owner, project_name), "run_uuid": run_uuid}
149
+ ctx.obj = {
150
+ "project": "{}/{}".format(owner_team, project_name),
151
+ "run_uuid": run_uuid,
152
+ }
140
153
  ctx.invoke(run_logs)
141
154
 
142
155
  def start_run_shell(run_uuid: str):
143
- ctx.obj = {"project": "{}/{}".format(owner, project_name), "run_uuid": run_uuid}
156
+ ctx.obj = {
157
+ "project": "{}/{}".format(owner_team, project_name),
158
+ "run_uuid": run_uuid,
159
+ }
144
160
  ctx.invoke(run_shell)
145
161
 
146
162
  def upload_run(run_uuid: str):
147
- ctx.obj = {"project": "{}/{}".format(owner, project_name), "run_uuid": run_uuid}
163
+ ctx.obj = {
164
+ "project": "{}/{}".format(owner_team, project_name),
165
+ "run_uuid": run_uuid,
166
+ }
148
167
  ctx.invoke(
149
168
  run_upload, path_to=upload_to, path_from=upload_from, sync_failure=True
150
169
  )
@@ -555,13 +574,14 @@ def run(
555
574
  Printer.print("Please customize the specification or disable the template!")
556
575
  sys.exit(1)
557
576
 
558
- owner, project_name = get_project_or_local(project, is_cli=True)
577
+ owner, team, project_name = get_project_or_local(project, is_cli=True)
559
578
  tags = validate_tags(tags, validate_yaml=True)
560
579
 
561
580
  _run(
562
581
  ctx=ctx,
563
582
  name=name,
564
583
  owner=owner,
584
+ team=team,
565
585
  project_name=project_name,
566
586
  description=description,
567
587
  tags=tags,