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.
Files changed (136) hide show
  1. {flyteplugins_union-0.4.2/src/flyteplugins_union.egg-info → flyteplugins_union-0.4.3}/PKG-INFO +2 -2
  2. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/licenses/BSL.txt +1 -1
  3. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/pyproject.toml +12 -1
  4. flyteplugins_union-0.4.3/src/flyteplugins/union/cli/ssh.py +181 -0
  5. flyteplugins_union-0.4.3/src/flyteplugins/union/debug.py +39 -0
  6. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/errors.py +13 -0
  7. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_base_volume.py +282 -40
  8. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_backend.py +13 -1
  9. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_ro_volume.py +13 -14
  10. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_rw_volume.py +17 -10
  11. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_volume_transformer.py +3 -4
  12. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/__init__.py +2 -0
  13. flyteplugins_union-0.4.3/src/flyteplugins/union/remote/_ssh_debug.py +456 -0
  14. flyteplugins_union-0.4.3/src/flyteplugins/union/ws_proxy.py +83 -0
  15. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3/src/flyteplugins_union.egg-info}/PKG-INFO +2 -2
  16. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/SOURCES.txt +6 -0
  17. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/entry_points.txt +4 -0
  18. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/requires.txt +1 -1
  19. flyteplugins_union-0.4.3/src/flyteplugins_union.egg-info/scm_file_list.json +168 -0
  20. flyteplugins_union-0.4.3/src/flyteplugins_union.egg-info/scm_version.json +8 -0
  21. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/LICENSE +0 -0
  22. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/README.md +0 -0
  23. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/README_PYPI.md +0 -0
  24. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/licenses/APL.txt +0 -0
  25. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/setup.cfg +0 -0
  26. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/__init__.py +0 -0
  27. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/__init__.py +0 -0
  28. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_tui/__init__.py +0 -0
  29. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_tui/_volume_explore.py +0 -0
  30. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_volume_index.py +0 -0
  31. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/_volume_session.py +0 -0
  32. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/api_key.py +0 -0
  33. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/assignment.py +0 -0
  34. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/cluster.py +0 -0
  35. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/cluster_pool.py +0 -0
  36. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/member.py +0 -0
  37. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/policy.py +0 -0
  38. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/queue.py +0 -0
  39. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/role.py +0 -0
  40. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/user.py +0 -0
  41. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/cli/volume.py +0 -0
  42. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/__init__.py +0 -0
  43. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/authorizer_connect.py +0 -0
  44. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/authorizer_pb2.py +0 -0
  45. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/authorizer_pb2.pyi +0 -0
  46. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/definition_pb2.py +0 -0
  47. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/definition_pb2.pyi +0 -0
  48. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/payload_pb2.py +0 -0
  49. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/authorizer/payload_pb2.pyi +0 -0
  50. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/cluster_connect.py +0 -0
  51. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/cluster_pb2.py +0 -0
  52. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/cluster_pb2.pyi +0 -0
  53. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/definition_pb2.py +0 -0
  54. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/definition_pb2.pyi +0 -0
  55. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/payload_pb2.py +0 -0
  56. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/cluster/payload_pb2.pyi +0 -0
  57. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/clusterpool_connect.py +0 -0
  58. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/clusterpool_pb2.py +0 -0
  59. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/clusterpool_pb2.pyi +0 -0
  60. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/payload_pb2.py +0 -0
  61. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/clusterpool/payload_pb2.pyi +0 -0
  62. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/authorization_pb2.py +0 -0
  63. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/authorization_pb2.pyi +0 -0
  64. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/cluster_pb2.py +0 -0
  65. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/cluster_pb2.pyi +0 -0
  66. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/deployment_pb2.py +0 -0
  67. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/deployment_pb2.pyi +0 -0
  68. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identifier_pb2.py +0 -0
  69. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identifier_pb2.pyi +0 -0
  70. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identity_pb2.py +0 -0
  71. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/identity_pb2.pyi +0 -0
  72. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/list_pb2.py +0 -0
  73. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/list_pb2.pyi +0 -0
  74. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/policy_pb2.py +0 -0
  75. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/policy_pb2.pyi +0 -0
  76. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/role_pb2.py +0 -0
  77. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/common/role_pb2.pyi +0 -0
  78. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_definition_pb2.py +0 -0
  79. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_definition_pb2.pyi +0 -0
  80. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_payload_pb2.py +0 -0
  81. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_payload_pb2.pyi +0 -0
  82. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_service_connect.py +0 -0
  83. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_service_pb2.py +0 -0
  84. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/app_service_pb2.pyi +0 -0
  85. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/enums_pb2.py +0 -0
  86. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/enums_pb2.pyi +0 -0
  87. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_payload_pb2.py +0 -0
  88. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_payload_pb2.pyi +0 -0
  89. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_service_connect.py +0 -0
  90. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_service_pb2.py +0 -0
  91. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/member_service_pb2.pyi +0 -0
  92. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_payload_pb2.py +0 -0
  93. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_payload_pb2.pyi +0 -0
  94. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_service_connect.py +0 -0
  95. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_service_pb2.py +0 -0
  96. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/policy_service_pb2.pyi +0 -0
  97. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_payload_pb2.py +0 -0
  98. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_payload_pb2.pyi +0 -0
  99. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_service_connect.py +0 -0
  100. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_service_pb2.py +0 -0
  101. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/role_service_pb2.pyi +0 -0
  102. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_payload_pb2.py +0 -0
  103. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_payload_pb2.pyi +0 -0
  104. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_service_connect.py +0 -0
  105. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_service_pb2.py +0 -0
  106. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/identity/user_service_pb2.pyi +0 -0
  107. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/queue/queue_connect.py +0 -0
  108. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/queue/queue_pb2.py +0 -0
  109. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/queue/queue_pb2.pyi +0 -0
  110. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/validate/__init__.py +0 -0
  111. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/validate/validate/__init__.py +0 -0
  112. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/internal/validate/validate/validate_pb2.py +0 -0
  113. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/__init__.py +0 -0
  114. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/__init__.py +0 -0
  115. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/__init__.py +0 -0
  116. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_common.py +0 -0
  117. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_metadata.py +0 -0
  118. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_redis.py +0 -0
  119. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/_sqlite.py +0 -0
  120. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/_juicefs/bin/.gitkeep +0 -0
  121. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/io/_internal/backend.py +0 -0
  122. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_api_key.py +0 -0
  123. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_assignment.py +0 -0
  124. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_cluster.py +0 -0
  125. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_cluster_pool.py +0 -0
  126. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_member.py +0 -0
  127. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_policy.py +0 -0
  128. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_queue.py +0 -0
  129. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_role.py +0 -0
  130. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_user.py +0 -0
  131. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/remote/_volume_explore.py +0 -0
  132. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/utils/__init__.py +0 -0
  133. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/utils/auth.py +0 -0
  134. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins/union/utils/image.py +0 -0
  135. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/dependency_links.txt +0 -0
  136. {flyteplugins_union-0.4.2 → flyteplugins_union-0.4.3}/src/flyteplugins_union.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyteplugins-union
3
- Version: 0.4.2
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.5.0,>=2.3.0
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-16
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.3.0,<2.5.0",
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