flyteplugins-union 0.4.2__tar.gz → 0.4.3__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.4.2/src/flyteplugins_union.egg-info → flyteplugins_union-0.4.3}/PKG-INFO +2 -2
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/licenses/BSL.txt +1 -1
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/pyproject.toml +12 -1
- flyteplugins_union-0.4.3/src/flyteplugins/union/cli/ssh.py +181 -0
- flyteplugins_union-0.4.3/src/flyteplugins/union/debug.py +39 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/errors.py +13 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_base_volume.py +282 -40
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_backend.py +13 -1
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_ro_volume.py +13 -14
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_rw_volume.py +17 -10
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_volume_transformer.py +3 -4
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/__init__.py +2 -0
- flyteplugins_union-0.4.3/src/flyteplugins/union/remote/_ssh_debug.py +456 -0
- flyteplugins_union-0.4.3/src/flyteplugins/union/ws_proxy.py +83 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3/src/flyteplugins_union.egg-info}/PKG-INFO +2 -2
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/SOURCES.txt +6 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/entry_points.txt +4 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/requires.txt +1 -1
- flyteplugins_union-0.4.3/src/flyteplugins_union.egg-info/scm_file_list.json +168 -0
- flyteplugins_union-0.4.3/src/flyteplugins_union.egg-info/scm_version.json +8 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/LICENSE +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/README.md +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/README_PYPI.md +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/licenses/APL.txt +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/setup.cfg +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_tui/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_tui/_volume_explore.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_volume_index.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_volume_session.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/api_key.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/assignment.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/cluster.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/cluster_pool.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/member.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/policy.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/queue.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/role.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/user.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/volume.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/authorizer_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/authorizer_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/authorizer_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/definition_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/definition_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/cluster_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/cluster_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/cluster_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/definition_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/definition_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/clusterpool_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/clusterpool_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/clusterpool_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/authorization_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/authorization_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/cluster_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/cluster_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/deployment_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/deployment_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identifier_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identifier_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identity_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identity_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/list_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/list_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/policy_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/policy_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/role_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/role_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_definition_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_definition_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_service_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_service_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_service_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/enums_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/enums_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_service_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_service_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_service_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_service_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_service_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_service_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_service_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_service_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_service_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_payload_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_payload_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_service_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_service_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_service_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/queue/queue_connect.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/queue/queue_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/queue/queue_pb2.pyi +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/validate/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/validate/validate/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/validate/validate/validate_pb2.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_common.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_metadata.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_redis.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_sqlite.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/bin/.gitkeep +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/backend.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_api_key.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_assignment.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_cluster.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_cluster_pool.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_member.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_policy.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_queue.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_role.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_user.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_volume_explore.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/utils/__init__.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/utils/auth.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/utils/image.py +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/dependency_links.txt +0 -0
- {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/top_level.txt +0 -0
{flyteplugins_union-0.4.2/src/flyteplugins_union.egg-info → flyteplugins_union-0.4.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flyteplugins-union
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
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/
|
|
@@ -19,7 +19,7 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
Requires-Dist: aiosqlite>=0.20.0
|
|
21
21
|
Requires-Dist: connectrpc>=0.9.0
|
|
22
|
-
Requires-Dist: flyte<2.
|
|
22
|
+
Requires-Dist: flyte<2.6.0,>=2.5.0
|
|
23
23
|
Requires-Dist: flyteidl2>=2.0.0
|
|
24
24
|
Requires-Dist: kubernetes>=27.2.0
|
|
25
25
|
Requires-Dist: pyyaml>=6.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-06-
|
|
20
|
+
Change Date: 2030-06-23
|
|
21
21
|
|
|
22
22
|
Change License: Apache License, Version 2.0
|
|
23
23
|
|
|
@@ -12,7 +12,7 @@ requires-python = ">=3.10"
|
|
|
12
12
|
dependencies = [
|
|
13
13
|
"aiosqlite>=0.20.0",
|
|
14
14
|
"connectrpc>=0.9.0",
|
|
15
|
-
"flyte>=2.
|
|
15
|
+
"flyte>=2.5.0,<2.6.0",
|
|
16
16
|
"flyteidl2>=2.0.0",
|
|
17
17
|
"kubernetes>=27.2.0",
|
|
18
18
|
"pyyaml>=6.0",
|
|
@@ -74,6 +74,10 @@ exclude = ["src/flyteplugins/union/internal"]
|
|
|
74
74
|
Homepage = "https://www.union.ai/"
|
|
75
75
|
Documentation = "https://docs.union.ai/"
|
|
76
76
|
|
|
77
|
+
[project.scripts]
|
|
78
|
+
# Stdio<->WebSocket proxy used as the ssh ProxyCommand for SSH-into-task debug.
|
|
79
|
+
flyte-ws-proxy = "flyteplugins.union.ws_proxy:main"
|
|
80
|
+
|
|
77
81
|
[project.entry-points."flyte.plugins.cli.commands"]
|
|
78
82
|
# CLI plugins for Union commands
|
|
79
83
|
"create.api-key" = "flyteplugins.union.cli.api_key:create_api_key"
|
|
@@ -109,6 +113,9 @@ Documentation = "https://docs.union.ai/"
|
|
|
109
113
|
# than an `explore.volume` entry because the plugin loader won't auto-create a
|
|
110
114
|
# missing `explore` verb group (it warns + skips).
|
|
111
115
|
"explore" = "flyteplugins.union.cli.volume:explore"
|
|
116
|
+
# Top-level `flyte connect` group (a single click.Group with an `ssh`
|
|
117
|
+
# subcommand → `flyte connect ssh`). Same top-level-group rationale as `explore`.
|
|
118
|
+
"connect" = "flyteplugins.union.cli.ssh:connect"
|
|
112
119
|
|
|
113
120
|
[project.entry-points."flyte.plugins.types"]
|
|
114
121
|
# Custom TypeTransformer that auto-commits a still-mounted Volume at
|
|
@@ -177,3 +184,7 @@ select = [
|
|
|
177
184
|
# VolumeExplore lazy-imports flyte.io / msgpack / boto3 / the Volume model so
|
|
178
185
|
# `import flyteplugins.union.remote` stays light for non-volume callers.
|
|
179
186
|
"src/flyteplugins/union/remote/_volume_explore.py" = ["PLC0415"]
|
|
187
|
+
# ssh-debug client lazy-imports the flyte auth machinery / remote objects so
|
|
188
|
+
# `flyte connect --help` and `import flyteplugins.union.remote` stay light.
|
|
189
|
+
"src/flyteplugins/union/cli/ssh.py" = ["PLC0415"]
|
|
190
|
+
"src/flyteplugins/union/remote/_ssh_debug.py" = ["PLC0415"]
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""``flyte connect ssh`` — attach your local desktop to a running debug task.
|
|
2
|
+
|
|
3
|
+
Counterpart to the pod-side ssh + WebSocket bridge (flyte core ``_F_E_SSH``).
|
|
4
|
+
Given a run launched in ssh-debug mode, this resolves the per-pod ``:6060``
|
|
5
|
+
route, mints (and caches) a Bearer token for the OAuth2 ingress, writes the
|
|
6
|
+
headers file, and prints a ready-to-paste ``~/.ssh/config`` block (optionally
|
|
7
|
+
writing it).
|
|
8
|
+
|
|
9
|
+
Registered as a top-level ``connect`` group (like ``explore``) rather than a
|
|
10
|
+
``connect.ssh`` entry, because the plugin loader won't auto-create a missing
|
|
11
|
+
``connect`` verb group.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
import rich_click as click
|
|
19
|
+
|
|
20
|
+
# Heavy imports (rich, remote objects) are deferred into the command body so
|
|
21
|
+
# registering the entry point stays fast.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.group("connect")
|
|
25
|
+
def connect() -> None:
|
|
26
|
+
"""Connect your local machine to a running Flyte task."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@connect.command("ssh")
|
|
30
|
+
@click.argument("run_name", required=True)
|
|
31
|
+
@click.argument("action_name", required=False)
|
|
32
|
+
@click.option("--user", type=str, default="root", show_default=True, help="SSH login user inside the pod.")
|
|
33
|
+
@click.option(
|
|
34
|
+
"--identity-file",
|
|
35
|
+
"identity_file",
|
|
36
|
+
type=str,
|
|
37
|
+
default=None,
|
|
38
|
+
help="Private key to authenticate with. Defaults to the auto-managed "
|
|
39
|
+
"~/.flyte/ssh-debug/id_ed25519 (created for you; no ssh-keygen needed).",
|
|
40
|
+
)
|
|
41
|
+
@click.option(
|
|
42
|
+
"--host-alias",
|
|
43
|
+
"--name",
|
|
44
|
+
"host_alias",
|
|
45
|
+
type=str,
|
|
46
|
+
default="flyte-debug",
|
|
47
|
+
show_default=True,
|
|
48
|
+
help="Host name to use in the ~/.ssh/config block (use distinct names to keep several runs side by side).",
|
|
49
|
+
)
|
|
50
|
+
@click.option(
|
|
51
|
+
"--api-key/--no-api-key",
|
|
52
|
+
"api_key",
|
|
53
|
+
default=False,
|
|
54
|
+
help="Authenticate the tunnel with a dedicated, long-lived API key (created/reused "
|
|
55
|
+
"as `flyte-ssh-debug`) instead of your interactive session token. Survives re-logins "
|
|
56
|
+
"and won't expire mid-session.",
|
|
57
|
+
)
|
|
58
|
+
@click.option(
|
|
59
|
+
"--refresh-token",
|
|
60
|
+
"refresh_token",
|
|
61
|
+
is_flag=True,
|
|
62
|
+
help="Force a fresh Bearer instead of reusing the cached one (use if you hit auth errors).",
|
|
63
|
+
)
|
|
64
|
+
@click.option(
|
|
65
|
+
"--write-config",
|
|
66
|
+
"write_config",
|
|
67
|
+
is_flag=True,
|
|
68
|
+
help="Write the Host block into ~/.ssh/config (replacing any prior block for the same name).",
|
|
69
|
+
)
|
|
70
|
+
@click.option(
|
|
71
|
+
"--timeout",
|
|
72
|
+
type=float,
|
|
73
|
+
default=300.0,
|
|
74
|
+
show_default=True,
|
|
75
|
+
help="Seconds to wait for the debug route to become ready.",
|
|
76
|
+
)
|
|
77
|
+
@click.pass_obj
|
|
78
|
+
def connect_ssh(
|
|
79
|
+
cfg,
|
|
80
|
+
run_name: str,
|
|
81
|
+
action_name: Optional[str],
|
|
82
|
+
user: str,
|
|
83
|
+
identity_file: str,
|
|
84
|
+
host_alias: str,
|
|
85
|
+
api_key: bool,
|
|
86
|
+
refresh_token: bool,
|
|
87
|
+
write_config: bool,
|
|
88
|
+
timeout: float,
|
|
89
|
+
) -> None:
|
|
90
|
+
"""Attach to a running ssh-debug task (launched with ``_F_E_SSH=1``).
|
|
91
|
+
|
|
92
|
+
Only RUN_NAME is required; ACTION_NAME defaults to the root action ``a0``.
|
|
93
|
+
The Bearer token is reused from a local cache between calls (no re-minting
|
|
94
|
+
every time); pass ``--refresh-token`` to force a new one.
|
|
95
|
+
|
|
96
|
+
Examples:
|
|
97
|
+
|
|
98
|
+
# Resolve + print the ssh-config for a debug run's root action
|
|
99
|
+
$ flyte connect ssh my-run
|
|
100
|
+
|
|
101
|
+
# A named host + login user, written into ~/.ssh/config
|
|
102
|
+
$ flyte connect ssh my-run --name my-run-dbg --user flyte --write-config
|
|
103
|
+
|
|
104
|
+
# Use a long-lived, user-specific API key for the tunnel auth
|
|
105
|
+
$ flyte connect ssh my-run --api-key --write-config
|
|
106
|
+
|
|
107
|
+
# Then connect (or VS Code -> Remote-SSH -> <name>)
|
|
108
|
+
$ ssh my-run-dbg
|
|
109
|
+
"""
|
|
110
|
+
from flyte.cli import _common as common
|
|
111
|
+
|
|
112
|
+
from flyteplugins.union.remote import SSHDebug
|
|
113
|
+
|
|
114
|
+
action_name = action_name or "a0"
|
|
115
|
+
cfg.init()
|
|
116
|
+
|
|
117
|
+
console = common.get_console()
|
|
118
|
+
with console.status(f"[bold]Resolving[/] ssh route for {run_name}/{action_name}…", spinner="dots"):
|
|
119
|
+
try:
|
|
120
|
+
info = SSHDebug.connect(
|
|
121
|
+
run_name,
|
|
122
|
+
action_name,
|
|
123
|
+
user=user,
|
|
124
|
+
identity_file=identity_file,
|
|
125
|
+
host_alias=host_alias,
|
|
126
|
+
use_api_key=api_key,
|
|
127
|
+
refresh_token=refresh_token,
|
|
128
|
+
timeout=timeout,
|
|
129
|
+
)
|
|
130
|
+
except TimeoutError as e:
|
|
131
|
+
raise click.ClickException(str(e)) from e
|
|
132
|
+
|
|
133
|
+
_emit(console, info, run_name=run_name, action_name=action_name, write_config=write_config)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _emit(console, info, *, run_name, action_name, write_config):
|
|
137
|
+
"""Write the Host block (optionally) and print the connect panel. Shared by
|
|
138
|
+
`flyte connect ssh` and `flyte debug`."""
|
|
139
|
+
import os
|
|
140
|
+
from pathlib import Path
|
|
141
|
+
|
|
142
|
+
from rich.panel import Panel
|
|
143
|
+
from rich.syntax import Syntax
|
|
144
|
+
|
|
145
|
+
if write_config:
|
|
146
|
+
ssh_config_path = Path(os.path.expanduser("~/.ssh/config"))
|
|
147
|
+
ssh_config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
148
|
+
existing = ssh_config_path.read_text() if ssh_config_path.exists() else ""
|
|
149
|
+
# Drop any prior `Host <alias>` block (header + its indented body) so
|
|
150
|
+
# re-running replaces stale config instead of shadowing it with a dup
|
|
151
|
+
# (ssh honors the first matching Host).
|
|
152
|
+
kept, skipping = [], False
|
|
153
|
+
for line in existing.splitlines():
|
|
154
|
+
if line.strip().startswith("Host ") and line.split()[1:] == [info.host_alias]:
|
|
155
|
+
skipping = True
|
|
156
|
+
continue
|
|
157
|
+
if skipping:
|
|
158
|
+
# Block body is blank or indented; ends at the next non-indented, non-blank line.
|
|
159
|
+
if line and not line[0].isspace():
|
|
160
|
+
skipping = False
|
|
161
|
+
else:
|
|
162
|
+
continue
|
|
163
|
+
kept.append(line)
|
|
164
|
+
new_text = "\n".join(kept).rstrip() + "\n\n" + info.ssh_config
|
|
165
|
+
ssh_config_path.write_text(new_text)
|
|
166
|
+
console.print(f"[green]Wrote[/] Host [bold]{info.host_alias}[/] to {ssh_config_path}")
|
|
167
|
+
|
|
168
|
+
console.print(
|
|
169
|
+
Panel.fit(
|
|
170
|
+
Syntax(info.ssh_config, "sshconfig", theme="ansi_dark", background_color="default"),
|
|
171
|
+
title=f"[bold]ssh -> {run_name}/{action_name}[/bold]",
|
|
172
|
+
subtitle=f"then: ssh {info.host_alias} (or VS Code Remote-SSH -> {info.host_alias})",
|
|
173
|
+
border_style="cyan",
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
if info.headers_file:
|
|
177
|
+
console.print(f"[dim]Bearer header written to {info.headers_file} (0600)[/dim]")
|
|
178
|
+
console.print(
|
|
179
|
+
f"[dim]Token expired / 401 on reconnect? Just re-run `flyte connect ssh {run_name}` "
|
|
180
|
+
f"(refreshes in place — no --write-config needed). For multi-day sessions use --api-key.[/dim]"
|
|
181
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""SSH-into-task debug helpers.
|
|
2
|
+
|
|
3
|
+
`with_debugcontext(...)` is `flyte.with_runcontext(...)` preconfigured for
|
|
4
|
+
ssh-into-task debug: it creates/uses the auto-managed debug keypair and sets the
|
|
5
|
+
``_F_E_SSH`` / ``_F_SSH_PK`` / ``_F_E_VS`` env vars, then forwards everything
|
|
6
|
+
else to `flyte.with_runcontext`. After the run starts, resolve the connection
|
|
7
|
+
with `SSHDebug.connect(run.name)` (or the `flyte connect ssh <run>` CLI).
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
```python
|
|
11
|
+
import flyte
|
|
12
|
+
from flyteplugins.union.debug import with_debugcontext, SSHDebug
|
|
13
|
+
|
|
14
|
+
flyte.init_from_config()
|
|
15
|
+
run = with_debugcontext().run(my_task, x=1)
|
|
16
|
+
print(SSHDebug.connect(run.name).ssh_config) # paste into ~/.ssh/config, then `ssh flyte-debug`
|
|
17
|
+
```
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from typing import Any, Dict, Optional
|
|
23
|
+
|
|
24
|
+
import flyte
|
|
25
|
+
|
|
26
|
+
from flyteplugins.union.remote._ssh_debug import SSHDebug, launch_env
|
|
27
|
+
|
|
28
|
+
__all__ = ["SSHDebug", "with_debugcontext"]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def with_debugcontext(mode: Any = None, *, env_vars: Optional[Dict[str, str]] = None, **kwargs):
|
|
32
|
+
"""Like `flyte.with_runcontext`, but preconfigured for ssh-into-task debug.
|
|
33
|
+
|
|
34
|
+
Ensures the auto-managed debug keypair exists and merges the ssh-debug env
|
|
35
|
+
(``_F_E_SSH`` / ``_F_SSH_PK`` / ``_F_E_VS``) into *env_vars*; all other
|
|
36
|
+
arguments are forwarded unchanged. Returns the same runner as
|
|
37
|
+
`with_runcontext`, so call ``.run(task, ...)`` on it.
|
|
38
|
+
"""
|
|
39
|
+
return flyte.with_runcontext(mode, env_vars=launch_env(env_vars), **kwargs)
|
|
@@ -53,6 +53,19 @@ class VolumeUnmountError(VolumeError):
|
|
|
53
53
|
_code = "VolumeUnmountFailed"
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
class VolumeUnmountUnsupportedError(VolumeUnmountError):
|
|
57
|
+
"""The runtime cannot unmount the FUSE client at all because ``fusermount``
|
|
58
|
+
can't reach its mount table (``/etc/mtab`` is missing, read-only, or
|
|
59
|
+
unwritable). Unlike a transient :class:`VolumeUnmountError` (EBUSY), retrying
|
|
60
|
+
won't help — the image is missing the ``/etc/mtab`` → ``/proc/self/mounts``
|
|
61
|
+
symlink most base images carry. The terminal seal treats this as recoverable:
|
|
62
|
+
it falls back to a keep-alive (live) commit, leaving the mount in place. A
|
|
63
|
+
kind of :class:`VolumeUnmountError`, so ``except VolumeUnmountError`` catches
|
|
64
|
+
it too."""
|
|
65
|
+
|
|
66
|
+
_code = "VolumeUnmountUnsupported"
|
|
67
|
+
|
|
68
|
+
|
|
56
69
|
class VolumeCommitError(VolumeError):
|
|
57
70
|
"""A keep-alive checkpoint could not be made durable: the writeback staging
|
|
58
71
|
queue did not finish uploading to object storage (it timed out, or its
|