flyteplugins-union 0.2.1__tar.gz → 0.3.0__tar.gz
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.
- {flyteplugins_union-0.2.1/src/flyteplugins_union.egg-info → flyteplugins_union-0.3.0}/PKG-INFO +3 -2
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/licenses/BSL.txt +1 -1
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/pyproject.toml +7 -5
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/api_key.py +11 -2
- flyteplugins_union-0.3.0/src/flyteplugins/union/cli/cluster.py +178 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/cli/queue.py +366 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/authorizer/authorizer_connect.py +1878 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/cluster_connect.py +513 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/cluster_pb2.py +42 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/cluster_pb2.pyi +6 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/definition_pb2.py +91 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/definition_pb2.pyi +295 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/payload_pb2.py +55 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/cluster/payload_pb2.pyi +109 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/authorization_pb2.py +2 -2
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/authorization_pb2.pyi +2 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/identifier_pb2.py +35 -27
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/identifier_pb2.pyi +12 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/identity_pb2.py +7 -3
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/identity_pb2.pyi +12 -2
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/role_pb2.py +2 -2
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/role_pb2.pyi +4 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/identity/app_payload_pb2.py +56 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/app_payload_pb2.pyi +4 -2
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/identity/app_service_connect.py +383 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/identity/member_service_connect.py +123 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/identity/policy_service_connect.py +448 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/identity/role_service_connect.py +513 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/identity/user_service_connect.py +448 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/queue/queue_connect.py +456 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/queue/queue_pb2.py +136 -0
- flyteplugins_union-0.3.0/src/flyteplugins/union/internal/queue/queue_pb2.pyi +176 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/__init__.py +3 -1
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/_api_key.py +24 -23
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/_assignment.py +9 -9
- flyteplugins_union-0.3.0/src/flyteplugins/union/remote/_cluster.py +234 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/_member.py +3 -3
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/_policy.py +13 -13
- flyteplugins_union-0.3.0/src/flyteplugins/union/remote/_queue.py +421 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/_role.py +11 -11
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/remote/_user.py +9 -9
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0/src/flyteplugins_union.egg-info}/PKG-INFO +3 -2
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins_union.egg-info/SOURCES.txt +20 -23
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins_union.egg-info/entry_points.txt +4 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins_union.egg-info/requires.txt +2 -1
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/authorizer/authorizer_pb2_grpc.py +0 -964
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/authorizer/definition_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/authorizer/payload_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/authorization_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/deployment_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/identifier_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/identity_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/list_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/policy_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/common/role_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/app_definition_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/app_payload_pb2.py +0 -56
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/app_payload_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/app_service_pb2_grpc.py +0 -198
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/enums_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/member_payload_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/member_service_pb2_grpc.py +0 -67
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/policy_payload_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/policy_service_pb2_grpc.py +0 -232
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/role_payload_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/role_service_pb2_grpc.py +0 -265
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/user_payload_pb2_grpc.py +0 -4
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/identity/user_service_pb2_grpc.py +0 -231
- flyteplugins_union-0.2.1/src/flyteplugins/union/internal/validate/validate/validate_pb2_grpc.py +0 -24
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/LICENSE +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/README.md +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/README_PYPI.md +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/licenses/APL.txt +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/setup.cfg +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/__init__.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/__init__.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/assignment.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/member.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/policy.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/role.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/cli/user.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/__init__.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/authorizer/authorizer_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/authorizer/authorizer_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/authorizer/definition_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/authorizer/definition_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/authorizer/payload_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/authorizer/payload_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/deployment_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/deployment_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/list_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/list_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/policy_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/common/policy_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/app_definition_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/app_definition_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/app_service_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/app_service_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/enums_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/enums_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/member_payload_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/member_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/member_service_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/member_service_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/policy_payload_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/policy_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/policy_service_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/policy_service_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/role_payload_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/role_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/role_service_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/role_service_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/user_payload_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/user_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/user_service_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/identity/user_service_pb2.pyi +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/validate/__init__.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/validate/validate/__init__.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/internal/validate/validate/validate_pb2.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/utils/__init__.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins/union/utils/auth.py +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins_union.egg-info/dependency_links.txt +0 -0
- {flyteplugins_union-0.2.1 → flyteplugins_union-0.3.0}/src/flyteplugins_union.egg-info/top_level.txt +0 -0
{flyteplugins_union-0.2.1/src/flyteplugins_union.egg-info → flyteplugins_union-0.3.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flyteplugins-union
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Union SDK - Proprietary extensions for Flyte
|
|
5
5
|
Author-email: unionai <info@union.ai>
|
|
6
6
|
Project-URL: Homepage, https://www.union.ai/
|
|
@@ -17,7 +17,8 @@ Classifier: Topic :: Software Development
|
|
|
17
17
|
Requires-Python: >=3.10
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: connectrpc>=0.9.0
|
|
21
|
+
Requires-Dist: flyte<2.5.0,>=2.1.0
|
|
21
22
|
Requires-Dist: flyteidl2>=2.0.0
|
|
22
23
|
Requires-Dist: pyyaml>=6.0
|
|
23
24
|
Requires-Dist: rich-click>=1.8.0
|
|
@@ -17,7 +17,7 @@ Additional Use Grant: You may make use of the Licensed Work, provided that
|
|
|
17
17
|
computer programs whose source code are controlled by
|
|
18
18
|
such third parties.
|
|
19
19
|
|
|
20
|
-
Change Date: 2030-
|
|
20
|
+
Change Date: 2030-05-06
|
|
21
21
|
|
|
22
22
|
Change License: Apache License, Version 2.0
|
|
23
23
|
|
|
@@ -10,7 +10,8 @@ description = "Union SDK - Proprietary extensions for Flyte"
|
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
dependencies = [
|
|
13
|
-
"
|
|
13
|
+
"connectrpc>=0.9.0",
|
|
14
|
+
"flyte>=2.1.0,<2.5.0",
|
|
14
15
|
"flyteidl2>=2.0.0",
|
|
15
16
|
"pyyaml>=6.0",
|
|
16
17
|
"rich-click>=1.8.0",
|
|
@@ -29,7 +30,6 @@ classifiers = [
|
|
|
29
30
|
|
|
30
31
|
[dependency-groups]
|
|
31
32
|
dev = [
|
|
32
|
-
"grpcio-tools>=1.71.0",
|
|
33
33
|
"build>=1.2.2.post1",
|
|
34
34
|
"mock>=5.2.0",
|
|
35
35
|
"pytest>=8.3.5",
|
|
@@ -63,6 +63,10 @@ Documentation = "https://docs.union.ai/"
|
|
|
63
63
|
"get.user" = "flyteplugins.union.cli.user:get_user"
|
|
64
64
|
"delete.user" = "flyteplugins.union.cli.user:delete_user"
|
|
65
65
|
"get.member" = "flyteplugins.union.cli.member:get_member"
|
|
66
|
+
"get.cluster" = "flyteplugins.union.cli.cluster:get_cluster"
|
|
67
|
+
"create.queue" = "flyteplugins.union.cli.queue:create_queue"
|
|
68
|
+
"get.queue" = "flyteplugins.union.cli.queue:get_queue"
|
|
69
|
+
"update.queue" = "flyteplugins.union.cli.queue:update_queue"
|
|
66
70
|
"create.assignment" = "flyteplugins.union.cli.assignment:create_assignment"
|
|
67
71
|
"get.assignment" = "flyteplugins.union.cli.assignment:get_assignment"
|
|
68
72
|
"delete.assignment" = "flyteplugins.union.cli.assignment:delete_assignment"
|
|
@@ -76,9 +80,7 @@ include = ["flyteplugins*"]
|
|
|
76
80
|
|
|
77
81
|
[tool.ruff]
|
|
78
82
|
line-length = 120
|
|
79
|
-
extend-exclude = [
|
|
80
|
-
"src/flyteplugins/union/internal",
|
|
81
|
-
]
|
|
83
|
+
extend-exclude = ["src/flyteplugins/union/internal"]
|
|
82
84
|
|
|
83
85
|
[tool.ruff.lint]
|
|
84
86
|
select = [
|
|
@@ -7,8 +7,14 @@ from flyteplugins.union.remote import ApiKey
|
|
|
7
7
|
|
|
8
8
|
@click.command("api-key")
|
|
9
9
|
@click.option("--name", type=str, help="Name for API key", required=True)
|
|
10
|
+
@click.option(
|
|
11
|
+
"--no-default-policies",
|
|
12
|
+
"skip_default_policy_assignments",
|
|
13
|
+
is_flag=True,
|
|
14
|
+
help="Skip attaching the server's default policies. Grant access explicitly via 'flyte create assignment'.",
|
|
15
|
+
)
|
|
10
16
|
@click.pass_obj
|
|
11
|
-
def create_api_key(cfg: common.CLIConfig, name: str):
|
|
17
|
+
def create_api_key(cfg: common.CLIConfig, name: str, skip_default_policy_assignments: bool):
|
|
12
18
|
"""
|
|
13
19
|
Create an API key for headless authentication.
|
|
14
20
|
|
|
@@ -22,6 +28,9 @@ def create_api_key(cfg: common.CLIConfig, name: str):
|
|
|
22
28
|
# Create an API key named "ci-pipeline"
|
|
23
29
|
$ flyte create api-key --name ci-pipeline
|
|
24
30
|
|
|
31
|
+
# Create a locked-down key with no default policy attachments
|
|
32
|
+
$ flyte create api-key --name ci-pipeline --no-default-policies
|
|
33
|
+
|
|
25
34
|
# The output will include an export command like:
|
|
26
35
|
# export FLYTE_API_KEY="<base64-encoded-credentials>"
|
|
27
36
|
"""
|
|
@@ -29,7 +38,7 @@ def create_api_key(cfg: common.CLIConfig, name: str):
|
|
|
29
38
|
cfg.init(project="", domain="")
|
|
30
39
|
|
|
31
40
|
try:
|
|
32
|
-
api_key = ApiKey.create(name=name)
|
|
41
|
+
api_key = ApiKey.create(name=name, skip_default_policy_assignments=skip_default_policy_assignments)
|
|
33
42
|
|
|
34
43
|
console = common.get_console()
|
|
35
44
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import rich_click as click
|
|
2
|
+
from flyte.cli import _common as common
|
|
3
|
+
|
|
4
|
+
from flyteplugins.union.remote import Cluster
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@click.command("cluster")
|
|
8
|
+
@click.argument("name", type=str, required=False)
|
|
9
|
+
@click.option("--limit", type=int, default=100, help="Maximum number of clusters to return.")
|
|
10
|
+
@click.pass_obj
|
|
11
|
+
def get_cluster(cfg: common.CLIConfig, name: str | None, limit: int):
|
|
12
|
+
"""Get a cluster or list all clusters.
|
|
13
|
+
|
|
14
|
+
If NAME is provided, fetch that specific cluster and render a detailed view.
|
|
15
|
+
Otherwise list all clusters.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
|
|
19
|
+
$ flyte --org my-org get cluster
|
|
20
|
+
|
|
21
|
+
$ flyte --org my-org get cluster my-cluster
|
|
22
|
+
"""
|
|
23
|
+
cfg.init(project="", domain="")
|
|
24
|
+
console = common.get_console()
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
if name:
|
|
28
|
+
cluster = Cluster.get(name)
|
|
29
|
+
if cfg.output_format in ("json", "json-raw"):
|
|
30
|
+
console.print(common.format(f"Cluster {name}", [cluster], cfg.output_format))
|
|
31
|
+
else:
|
|
32
|
+
console.print(_render_cluster_detail(cluster))
|
|
33
|
+
else:
|
|
34
|
+
clusters = list(Cluster.listall(limit=limit))
|
|
35
|
+
if not clusters:
|
|
36
|
+
console.print("[yellow]No clusters found.[/yellow]")
|
|
37
|
+
return
|
|
38
|
+
enabled = [c for c in clusters if c.state == "enabled"]
|
|
39
|
+
disabled = [c for c in clusters if c.state != "enabled"]
|
|
40
|
+
if enabled:
|
|
41
|
+
console.print(common.format("Enabled Clusters", enabled, cfg.output_format))
|
|
42
|
+
if disabled:
|
|
43
|
+
if enabled:
|
|
44
|
+
console.print()
|
|
45
|
+
console.print(common.format("Disabled Clusters", disabled, cfg.output_format))
|
|
46
|
+
except Exception as e:
|
|
47
|
+
raise click.ClickException(f"Unable to get clusters: {e}") from e
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
# Detailed single-cluster rendering
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _render_cluster_detail(cluster: Cluster):
|
|
56
|
+
"""Render a multi-section Panel for a single cluster."""
|
|
57
|
+
from rich.panel import Panel # noqa: PLC0415
|
|
58
|
+
from rich.table import Table # noqa: PLC0415
|
|
59
|
+
|
|
60
|
+
outer = Table.grid(padding=(0, 0))
|
|
61
|
+
outer.add_column(ratio=1)
|
|
62
|
+
|
|
63
|
+
sections = [
|
|
64
|
+
("Identity", _kv_table(cluster, [("name", "name"), ("organization", "organization")])),
|
|
65
|
+
(
|
|
66
|
+
"State",
|
|
67
|
+
_kv_table(
|
|
68
|
+
cluster,
|
|
69
|
+
[
|
|
70
|
+
("state", "state"),
|
|
71
|
+
("health", "health_display"),
|
|
72
|
+
("unhealthy reasons", "_unhealthy_reasons_str"),
|
|
73
|
+
],
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
(
|
|
77
|
+
"Cloud",
|
|
78
|
+
_kv_table(
|
|
79
|
+
cluster,
|
|
80
|
+
[
|
|
81
|
+
("host", "cloud_host_name"),
|
|
82
|
+
("storage", "storage_type"),
|
|
83
|
+
("bucket", "bucket_name"),
|
|
84
|
+
("region", "bucket_region"),
|
|
85
|
+
("metadata prefix", "metadata_bucket_prefix"),
|
|
86
|
+
("gcp project", "gcp_project_id"),
|
|
87
|
+
("user role", "user_role"),
|
|
88
|
+
("operator app", "operator_app_id"),
|
|
89
|
+
],
|
|
90
|
+
skip_empty=True,
|
|
91
|
+
),
|
|
92
|
+
),
|
|
93
|
+
(
|
|
94
|
+
"Config",
|
|
95
|
+
_kv_table(
|
|
96
|
+
cluster,
|
|
97
|
+
[
|
|
98
|
+
("assigned", "assigned_config_id"),
|
|
99
|
+
("synced", "synced_config_id"),
|
|
100
|
+
("synced at", "synced_at"),
|
|
101
|
+
("drift", "_drift_display"),
|
|
102
|
+
],
|
|
103
|
+
skip_empty=True,
|
|
104
|
+
),
|
|
105
|
+
),
|
|
106
|
+
(
|
|
107
|
+
"Capacity",
|
|
108
|
+
_kv_table(cluster, [("resources", "capacity"), ("ingress (dataplane)", "dataplane_ingress_enabled")]),
|
|
109
|
+
),
|
|
110
|
+
(
|
|
111
|
+
"Tunnel",
|
|
112
|
+
_kv_table(
|
|
113
|
+
cluster,
|
|
114
|
+
[("status", "tunnel_status_display"), ("public url", "tunnel_url")],
|
|
115
|
+
skip_empty=True,
|
|
116
|
+
),
|
|
117
|
+
),
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
for title, body in sections:
|
|
121
|
+
if body is None:
|
|
122
|
+
continue
|
|
123
|
+
outer.add_row(Panel(body, title=f"[bold]{title}[/bold]", border_style="dim"))
|
|
124
|
+
|
|
125
|
+
if cluster.queues:
|
|
126
|
+
outer.add_row(_render_queues_panel(cluster.queues))
|
|
127
|
+
|
|
128
|
+
return outer
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _kv_table(cluster: Cluster, fields: list[tuple[str, str]], *, skip_empty: bool = False):
|
|
132
|
+
"""Render label / value rows. Returns None when skip_empty and every value is empty."""
|
|
133
|
+
from rich.table import Table # noqa: PLC0415
|
|
134
|
+
from rich.text import Text # noqa: PLC0415
|
|
135
|
+
|
|
136
|
+
rows = []
|
|
137
|
+
for label, accessor in fields:
|
|
138
|
+
value = _accessor(cluster, accessor)
|
|
139
|
+
if skip_empty and not value and value is not False:
|
|
140
|
+
continue
|
|
141
|
+
rows.append((label, value))
|
|
142
|
+
|
|
143
|
+
if not rows:
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
t = Table.grid(padding=(0, 2))
|
|
147
|
+
t.add_column(style="dim", no_wrap=True)
|
|
148
|
+
t.add_column()
|
|
149
|
+
for label, value in rows:
|
|
150
|
+
t.add_row(label, Text.from_markup(str(value)) if value != "" else Text("—", style="dim"))
|
|
151
|
+
return t
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _accessor(cluster: Cluster, name: str):
|
|
155
|
+
"""Pull a property/value from the cluster, or compute a small helper string."""
|
|
156
|
+
if name == "_unhealthy_reasons_str":
|
|
157
|
+
return "; ".join(cluster.unhealthy_reasons) if cluster.unhealthy_reasons else ""
|
|
158
|
+
if name == "_drift_display":
|
|
159
|
+
if not cluster.assigned_config_id:
|
|
160
|
+
return ""
|
|
161
|
+
return "[bright_red]drifted[/bright_red]" if cluster.config_drift else "[green]in sync[/green]"
|
|
162
|
+
return getattr(cluster, name)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _render_queues_panel(queues: list[dict]):
|
|
166
|
+
"""Render the cluster's bound queues as a small panel."""
|
|
167
|
+
from rich.panel import Panel # noqa: PLC0415
|
|
168
|
+
from rich.table import Table # noqa: PLC0415
|
|
169
|
+
|
|
170
|
+
t = Table.grid(padding=(0, 2))
|
|
171
|
+
t.add_column(style="dim", no_wrap=True)
|
|
172
|
+
t.add_column()
|
|
173
|
+
for q in queues:
|
|
174
|
+
scope_parts = [s for s in (q.get("project"), q.get("domain")) if s]
|
|
175
|
+
scope = "/".join(scope_parts) if scope_parts else "—"
|
|
176
|
+
t.add_row(q["name"], scope)
|
|
177
|
+
|
|
178
|
+
return Panel(t, title=f"[bold]Queues ({len(queues)})[/bold]", border_style="dim")
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import rich_click as click
|
|
2
|
+
|
|
3
|
+
# All heavy imports (yaml, rich.*, remote objects) are deferred to inside
|
|
4
|
+
# command functions so that registering CLI entry points stays fast.
|
|
5
|
+
from flyteplugins.union.remote._queue import FAIRNESS_VALUES, PRIORITY_VALUES
|
|
6
|
+
|
|
7
|
+
_PRIORITY_CHOICES = click.Choice(list(PRIORITY_VALUES), case_sensitive=False)
|
|
8
|
+
_FAIRNESS_CHOICES = click.Choice(list(FAIRNESS_VALUES), case_sensitive=False)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
# create queue
|
|
13
|
+
# ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.command("queue")
|
|
17
|
+
@click.argument("name", type=str)
|
|
18
|
+
@click.option("--run-concurrency", type=int, required=True, help="Max concurrent runs (required)")
|
|
19
|
+
@click.option("--action-concurrency", type=int, required=True, help="Max concurrent actions (required)")
|
|
20
|
+
@click.option("--depth", type=int, default=10000, show_default=True, help="Max queue depth")
|
|
21
|
+
@click.option("--priority", type=_PRIORITY_CHOICES, default="medium", show_default=True, help="Queue priority")
|
|
22
|
+
@click.option(
|
|
23
|
+
"--fairness",
|
|
24
|
+
type=_FAIRNESS_CHOICES,
|
|
25
|
+
default="round_robin",
|
|
26
|
+
show_default=True,
|
|
27
|
+
help="Fairness algorithm",
|
|
28
|
+
)
|
|
29
|
+
@click.option("--cluster", "clusters", type=str, multiple=True, help="Target cluster(s). Repeat for multiple.")
|
|
30
|
+
@click.option("--project", type=str, default="", help="Scope queue to a project")
|
|
31
|
+
@click.option("--domain", type=str, default="", help="Scope queue to a domain")
|
|
32
|
+
@click.pass_obj
|
|
33
|
+
def create_queue(
|
|
34
|
+
cfg,
|
|
35
|
+
name: str,
|
|
36
|
+
run_concurrency: int,
|
|
37
|
+
action_concurrency: int,
|
|
38
|
+
depth: int,
|
|
39
|
+
priority: str,
|
|
40
|
+
fairness: str,
|
|
41
|
+
clusters: tuple[str, ...],
|
|
42
|
+
project: str,
|
|
43
|
+
domain: str,
|
|
44
|
+
):
|
|
45
|
+
"""Create a scheduling queue.
|
|
46
|
+
|
|
47
|
+
Examples:
|
|
48
|
+
|
|
49
|
+
$ flyte create queue my-queue --run-concurrency 100 --action-concurrency 1000
|
|
50
|
+
|
|
51
|
+
$ flyte create queue gpu-queue --run-concurrency 50 --action-concurrency 500 \\
|
|
52
|
+
--priority min --cluster gpu-cluster-1
|
|
53
|
+
|
|
54
|
+
$ flyte create queue backfill --run-concurrency 10 --action-concurrency 100 \\
|
|
55
|
+
--depth 5000 --priority max
|
|
56
|
+
|
|
57
|
+
$ flyte create queue team-queue --run-concurrency 100 --action-concurrency 1000 \\
|
|
58
|
+
--project my-project --domain production
|
|
59
|
+
"""
|
|
60
|
+
from flyte.cli import _common as common # noqa: PLC0415
|
|
61
|
+
|
|
62
|
+
from flyteplugins.union.remote import Queue # noqa: PLC0415
|
|
63
|
+
|
|
64
|
+
cfg.init(project="", domain="")
|
|
65
|
+
console = common.get_console()
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
queue = Queue.create(
|
|
69
|
+
name,
|
|
70
|
+
org=cfg.org,
|
|
71
|
+
domain=domain,
|
|
72
|
+
project=project,
|
|
73
|
+
run_concurrency=run_concurrency,
|
|
74
|
+
action_concurrency=action_concurrency,
|
|
75
|
+
depth=depth,
|
|
76
|
+
priority=priority,
|
|
77
|
+
fairness=fairness,
|
|
78
|
+
clusters=list(clusters) if clusters else None,
|
|
79
|
+
)
|
|
80
|
+
console.print(f"[green]✓[/green] Successfully created queue: [cyan]{queue.name}[/cyan]")
|
|
81
|
+
console.print(common.format(f"Queue {queue.name}", [queue], "json"))
|
|
82
|
+
except Exception as e:
|
|
83
|
+
raise click.ClickException(f"Unable to create queue: {e}") from e
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ---------------------------------------------------------------------------
|
|
87
|
+
# get queue
|
|
88
|
+
# ---------------------------------------------------------------------------
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@click.command("queue")
|
|
92
|
+
@click.argument("name", type=str, required=False)
|
|
93
|
+
@click.option("--project", type=str, default="", help="Scope to a project")
|
|
94
|
+
@click.option("--domain", type=str, default="", help="Scope to a domain")
|
|
95
|
+
@click.option("--limit", type=int, default=100, help="Maximum number of queues to return")
|
|
96
|
+
@click.option("--watch", is_flag=True, help="Stream live queue metrics (requires NAME)")
|
|
97
|
+
@click.pass_obj
|
|
98
|
+
def get_queue(cfg, name: str | None, project: str, domain: str, limit: int, watch: bool):
|
|
99
|
+
"""Get a queue or list all queues.
|
|
100
|
+
|
|
101
|
+
If NAME is provided, fetch that specific queue with its current metrics.
|
|
102
|
+
Use --watch to stream live metrics with progress bars.
|
|
103
|
+
Otherwise list all queues.
|
|
104
|
+
|
|
105
|
+
Examples:
|
|
106
|
+
|
|
107
|
+
$ flyte get queue
|
|
108
|
+
|
|
109
|
+
$ flyte get queue my-queue
|
|
110
|
+
|
|
111
|
+
$ flyte get queue my-queue --watch
|
|
112
|
+
"""
|
|
113
|
+
if watch and not name:
|
|
114
|
+
raise click.ClickException("--watch requires a queue NAME")
|
|
115
|
+
|
|
116
|
+
from flyte.cli import _common as common # noqa: PLC0415
|
|
117
|
+
|
|
118
|
+
from flyteplugins.union.remote import Queue # noqa: PLC0415
|
|
119
|
+
|
|
120
|
+
cfg.init(project="", domain="")
|
|
121
|
+
console = common.get_console()
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
if name and watch:
|
|
125
|
+
_watch_queue(console, name, cfg.org, domain, project)
|
|
126
|
+
elif name:
|
|
127
|
+
queue = Queue.get(name, org=cfg.org, domain=domain, project=project)
|
|
128
|
+
console.print(common.format(f"Queue {name}", [queue], "json"))
|
|
129
|
+
|
|
130
|
+
# Show metrics snapshot
|
|
131
|
+
try:
|
|
132
|
+
metrics = Queue.details(name, org=cfg.org, domain=domain, project=project)
|
|
133
|
+
console.print(_render_metrics(metrics, queue))
|
|
134
|
+
except Exception:
|
|
135
|
+
pass # Metrics are best-effort
|
|
136
|
+
else:
|
|
137
|
+
queues = list(Queue.listall(org=cfg.org, limit=limit))
|
|
138
|
+
if not queues:
|
|
139
|
+
console.print("[yellow]No queues found.[/yellow]")
|
|
140
|
+
return
|
|
141
|
+
console.print(common.format("Queues", queues, cfg.output_format))
|
|
142
|
+
except Exception as e:
|
|
143
|
+
raise click.ClickException(f"Unable to get queue(s): {e}") from e
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# ---------------------------------------------------------------------------
|
|
147
|
+
# Watch display helpers
|
|
148
|
+
# ---------------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _pct_color(ratio: float) -> str:
|
|
152
|
+
if ratio >= 0.9:
|
|
153
|
+
return "bright_red"
|
|
154
|
+
if ratio >= 0.7:
|
|
155
|
+
return "yellow"
|
|
156
|
+
return "medium_purple1"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _bar_style(ratio: float) -> str:
|
|
160
|
+
if ratio >= 0.9:
|
|
161
|
+
return "bright_red"
|
|
162
|
+
if ratio >= 0.7:
|
|
163
|
+
return "yellow"
|
|
164
|
+
return "medium_purple1"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _render_metric_block(label: str, used: int, cap: int):
|
|
168
|
+
"""Render a single metric: header row with label/value/pct, then a slim bar."""
|
|
169
|
+
from rich.progress_bar import ProgressBar # noqa: PLC0415
|
|
170
|
+
from rich.table import Table # noqa: PLC0415
|
|
171
|
+
from rich.text import Text # noqa: PLC0415
|
|
172
|
+
|
|
173
|
+
ratio = used / cap if cap > 0 else 0
|
|
174
|
+
pct = ratio * 100
|
|
175
|
+
color = _pct_color(ratio)
|
|
176
|
+
style = _bar_style(ratio)
|
|
177
|
+
|
|
178
|
+
block = Table.grid(padding=0)
|
|
179
|
+
block.add_column("label", ratio=1)
|
|
180
|
+
block.add_column("value", justify="right")
|
|
181
|
+
block.add_column("pct", justify="right", min_width=6)
|
|
182
|
+
|
|
183
|
+
block.add_row(
|
|
184
|
+
Text(label, style="bold"),
|
|
185
|
+
Text(f"{used:,} / {cap:,}", style="dim"),
|
|
186
|
+
Text(f"{pct:.0f}%", style=color),
|
|
187
|
+
)
|
|
188
|
+
bar = ProgressBar(
|
|
189
|
+
total=max(cap, 1),
|
|
190
|
+
completed=min(used, cap),
|
|
191
|
+
width=None,
|
|
192
|
+
style="bar.back",
|
|
193
|
+
complete_style=style,
|
|
194
|
+
finished_style=style,
|
|
195
|
+
)
|
|
196
|
+
# bar spans all columns
|
|
197
|
+
block.add_row(bar, "", "")
|
|
198
|
+
return block
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _render_metrics(metrics: dict, queue=None):
|
|
202
|
+
"""Build a rich Panel showing queue metrics with slim progress bars."""
|
|
203
|
+
from datetime import datetime, timezone # noqa: PLC0415
|
|
204
|
+
|
|
205
|
+
from rich.panel import Panel # noqa: PLC0415
|
|
206
|
+
from rich.table import Table # noqa: PLC0415
|
|
207
|
+
|
|
208
|
+
outer = Table.grid(padding=(1, 2))
|
|
209
|
+
outer.add_column(ratio=1)
|
|
210
|
+
|
|
211
|
+
outer.add_row(_render_metric_block("Runs in-flight", metrics["runs_in_flight"], metrics["run_concurrency"]))
|
|
212
|
+
outer.add_row(
|
|
213
|
+
_render_metric_block("Actions in-flight", metrics["actions_in_flight"], metrics["action_concurrency"])
|
|
214
|
+
)
|
|
215
|
+
outer.add_row(_render_metric_block("Queue depth", metrics["current_depth"], metrics["depth"]))
|
|
216
|
+
|
|
217
|
+
ts = datetime.fromtimestamp(metrics["observed_at"], tz=timezone.utc).strftime("%H:%M:%S UTC")
|
|
218
|
+
subtitle_parts = [f"last updated {ts}"]
|
|
219
|
+
|
|
220
|
+
status_str = ""
|
|
221
|
+
if queue:
|
|
222
|
+
status_color = {"active": "green", "draining": "yellow", "drained": "dim"}.get(queue.status, "white")
|
|
223
|
+
status_str = f" [{status_color}]{queue.status}[/{status_color}]"
|
|
224
|
+
subtitle_parts.append(f"priority: {queue.priority}")
|
|
225
|
+
subtitle_parts.append(f"fairness: {queue.fairness}")
|
|
226
|
+
if queue.clusters:
|
|
227
|
+
subtitle_parts.append(f"clusters: {', '.join(queue.clusters)}")
|
|
228
|
+
|
|
229
|
+
title = f"[bold]{metrics['name']}[/bold]{status_str}"
|
|
230
|
+
subtitle = " | ".join(subtitle_parts)
|
|
231
|
+
return Panel(outer, title=title, subtitle=f"[dim]{subtitle}[/dim]", border_style="dim")
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _watch_queue(console, name: str, org: str, domain: str, project: str) -> None:
|
|
235
|
+
"""Stream live queue metrics using rich Live display."""
|
|
236
|
+
from rich.console import Console # noqa: PLC0415
|
|
237
|
+
from rich.live import Live # noqa: PLC0415
|
|
238
|
+
|
|
239
|
+
from flyteplugins.union.remote import Queue # noqa: PLC0415
|
|
240
|
+
|
|
241
|
+
queue = Queue.get(name, org=org, domain=domain, project=project)
|
|
242
|
+
console.print(f"Watching queue [cyan]{name}[/cyan] (Ctrl+C to stop)\n")
|
|
243
|
+
|
|
244
|
+
# Use a console that auto-detects the real terminal width so that
|
|
245
|
+
# Live's cursor-up count matches the actual number of physical lines.
|
|
246
|
+
live_console = Console(force_terminal=True)
|
|
247
|
+
try:
|
|
248
|
+
with Live(console=live_console, refresh_per_second=4) as live:
|
|
249
|
+
for metrics in Queue.watch(name, org=org, domain=domain, project=project):
|
|
250
|
+
# Re-fetch queue config occasionally to pick up status changes
|
|
251
|
+
try:
|
|
252
|
+
queue = Queue.get(name, org=org, domain=domain, project=project)
|
|
253
|
+
except Exception:
|
|
254
|
+
pass
|
|
255
|
+
live.update(_render_metrics(metrics, queue))
|
|
256
|
+
except KeyboardInterrupt:
|
|
257
|
+
console.print("\n[dim]Watch stopped.[/dim]")
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
# ---------------------------------------------------------------------------
|
|
261
|
+
# YAML helpers for interactive editing
|
|
262
|
+
# ---------------------------------------------------------------------------
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _queue_to_yaml(queue) -> str:
|
|
266
|
+
"""Serialize a Queue to YAML for interactive editing."""
|
|
267
|
+
import yaml as _yaml # noqa: PLC0415
|
|
268
|
+
|
|
269
|
+
data = {
|
|
270
|
+
"name": queue.name,
|
|
271
|
+
"run_concurrency": queue.run_concurrency,
|
|
272
|
+
"action_concurrency": queue.action_concurrency,
|
|
273
|
+
"depth": queue.depth,
|
|
274
|
+
"priority": queue.priority,
|
|
275
|
+
"fairness": queue.fairness,
|
|
276
|
+
"clusters": queue.clusters,
|
|
277
|
+
}
|
|
278
|
+
if queue.project:
|
|
279
|
+
data["project"] = queue.project
|
|
280
|
+
if queue.domain:
|
|
281
|
+
data["domain"] = queue.domain
|
|
282
|
+
comment = (
|
|
283
|
+
"# Edit queue configuration below.\n"
|
|
284
|
+
"# Priority: min, medium, max\n"
|
|
285
|
+
"# Fairness: round_robin, shuffle_interleave\n"
|
|
286
|
+
"# Clusters: list of cluster names, or ['*'] for all\n"
|
|
287
|
+
)
|
|
288
|
+
return comment + "\n" + _yaml.safe_dump(data, default_flow_style=False, sort_keys=False)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
# ---------------------------------------------------------------------------
|
|
292
|
+
# update queue
|
|
293
|
+
# ---------------------------------------------------------------------------
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
@click.command("queue")
|
|
297
|
+
@click.argument("name", type=str)
|
|
298
|
+
@click.option("--project", type=str, default="", help="Scope to a project")
|
|
299
|
+
@click.option("--domain", type=str, default="", help="Scope to a domain")
|
|
300
|
+
@click.option("--drain", is_flag=True, help="Begin draining the queue")
|
|
301
|
+
@click.option("--activate", is_flag=True, help="Re-activate a draining or drained queue")
|
|
302
|
+
@click.option("--edit", "edit_mode", is_flag=True, help="Open an editor to modify queue settings")
|
|
303
|
+
@click.pass_obj
|
|
304
|
+
def update_queue(cfg, name: str, project: str, domain: str, drain: bool, activate: bool, edit_mode: bool):
|
|
305
|
+
"""Update a queue.
|
|
306
|
+
|
|
307
|
+
Use --drain to begin draining (stops new submissions).
|
|
308
|
+
Use --activate to re-activate a draining or drained queue.
|
|
309
|
+
Use --edit to interactively modify queue configuration.
|
|
310
|
+
|
|
311
|
+
Examples:
|
|
312
|
+
|
|
313
|
+
$ flyte update queue my-queue --drain
|
|
314
|
+
|
|
315
|
+
$ flyte update queue my-queue --activate
|
|
316
|
+
|
|
317
|
+
$ flyte update queue my-queue --edit
|
|
318
|
+
"""
|
|
319
|
+
if drain and activate:
|
|
320
|
+
raise click.ClickException("Cannot specify both --drain and --activate")
|
|
321
|
+
if not drain and not activate and not edit_mode:
|
|
322
|
+
raise click.ClickException("Must specify --drain, --activate, or --edit")
|
|
323
|
+
|
|
324
|
+
import yaml as _yaml # noqa: PLC0415, I001
|
|
325
|
+
from flyte.cli import _common as common # noqa: PLC0415
|
|
326
|
+
from flyteplugins.union.cli import edit_with_retry # noqa: PLC0415
|
|
327
|
+
from flyteplugins.union.remote import Queue # noqa: PLC0415
|
|
328
|
+
|
|
329
|
+
cfg.init(project="", domain="")
|
|
330
|
+
console = common.get_console()
|
|
331
|
+
|
|
332
|
+
try:
|
|
333
|
+
if drain:
|
|
334
|
+
queue = Queue.drain(name, org=cfg.org, domain=domain, project=project)
|
|
335
|
+
console.print(f"[green]✓[/green] Queue [cyan]{name}[/cyan] is now draining")
|
|
336
|
+
console.print(common.format(f"Queue {name}", [queue], "json"))
|
|
337
|
+
elif activate:
|
|
338
|
+
queue = Queue.activate(name, org=cfg.org, domain=domain, project=project)
|
|
339
|
+
console.print(f"[green]✓[/green] Queue [cyan]{name}[/cyan] is now active")
|
|
340
|
+
console.print(common.format(f"Queue {name}", [queue], "json"))
|
|
341
|
+
else:
|
|
342
|
+
# Interactive edit
|
|
343
|
+
current = Queue.get(name, org=cfg.org, domain=domain, project=project)
|
|
344
|
+
yaml_text = _queue_to_yaml(current)
|
|
345
|
+
|
|
346
|
+
def _apply(edited_yaml):
|
|
347
|
+
data = _yaml.safe_load(edited_yaml)
|
|
348
|
+
clusters = data.get("clusters")
|
|
349
|
+
return Queue.update(
|
|
350
|
+
name,
|
|
351
|
+
org=cfg.org,
|
|
352
|
+
domain=domain,
|
|
353
|
+
project=project,
|
|
354
|
+
run_concurrency=data.get("run_concurrency"),
|
|
355
|
+
action_concurrency=data.get("action_concurrency"),
|
|
356
|
+
depth=data.get("depth"),
|
|
357
|
+
priority=data.get("priority"),
|
|
358
|
+
fairness=data.get("fairness"),
|
|
359
|
+
clusters=clusters,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
result = edit_with_retry(yaml_text, _apply, console=console, noun="queue")
|
|
363
|
+
if result and result != "no_changes":
|
|
364
|
+
console.print(f"[green]✓[/green] Successfully updated queue: [cyan]{name}[/cyan]")
|
|
365
|
+
except Exception as e:
|
|
366
|
+
raise click.ClickException(f"Unable to update queue: {e}") from e
|