flyte 0.0.1b0__py3-none-any.whl → 2.0.0b46__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. flyte/__init__.py +83 -30
  2. flyte/_bin/connect.py +61 -0
  3. flyte/_bin/debug.py +38 -0
  4. flyte/_bin/runtime.py +87 -19
  5. flyte/_bin/serve.py +351 -0
  6. flyte/_build.py +3 -2
  7. flyte/_cache/cache.py +6 -5
  8. flyte/_cache/local_cache.py +216 -0
  9. flyte/_code_bundle/_ignore.py +31 -5
  10. flyte/_code_bundle/_packaging.py +42 -11
  11. flyte/_code_bundle/_utils.py +57 -34
  12. flyte/_code_bundle/bundle.py +130 -27
  13. flyte/_constants.py +1 -0
  14. flyte/_context.py +21 -5
  15. flyte/_custom_context.py +73 -0
  16. flyte/_debug/constants.py +37 -0
  17. flyte/_debug/utils.py +17 -0
  18. flyte/_debug/vscode.py +315 -0
  19. flyte/_deploy.py +396 -75
  20. flyte/_deployer.py +109 -0
  21. flyte/_environment.py +94 -11
  22. flyte/_excepthook.py +37 -0
  23. flyte/_group.py +2 -1
  24. flyte/_hash.py +1 -16
  25. flyte/_image.py +544 -234
  26. flyte/_initialize.py +443 -294
  27. flyte/_interface.py +40 -5
  28. flyte/_internal/controllers/__init__.py +22 -8
  29. flyte/_internal/controllers/_local_controller.py +159 -35
  30. flyte/_internal/controllers/_trace.py +18 -10
  31. flyte/_internal/controllers/remote/__init__.py +38 -9
  32. flyte/_internal/controllers/remote/_action.py +82 -12
  33. flyte/_internal/controllers/remote/_client.py +6 -2
  34. flyte/_internal/controllers/remote/_controller.py +290 -64
  35. flyte/_internal/controllers/remote/_core.py +155 -95
  36. flyte/_internal/controllers/remote/_informer.py +40 -20
  37. flyte/_internal/controllers/remote/_service_protocol.py +2 -2
  38. flyte/_internal/imagebuild/__init__.py +2 -10
  39. flyte/_internal/imagebuild/docker_builder.py +391 -84
  40. flyte/_internal/imagebuild/image_builder.py +111 -55
  41. flyte/_internal/imagebuild/remote_builder.py +409 -0
  42. flyte/_internal/imagebuild/utils.py +79 -0
  43. flyte/_internal/resolvers/_app_env_module.py +92 -0
  44. flyte/_internal/resolvers/_task_module.py +5 -38
  45. flyte/_internal/resolvers/app_env.py +26 -0
  46. flyte/_internal/resolvers/common.py +8 -1
  47. flyte/_internal/resolvers/default.py +2 -2
  48. flyte/_internal/runtime/convert.py +322 -33
  49. flyte/_internal/runtime/entrypoints.py +106 -18
  50. flyte/_internal/runtime/io.py +71 -23
  51. flyte/_internal/runtime/resources_serde.py +21 -7
  52. flyte/_internal/runtime/reuse.py +125 -0
  53. flyte/_internal/runtime/rusty.py +196 -0
  54. flyte/_internal/runtime/task_serde.py +239 -66
  55. flyte/_internal/runtime/taskrunner.py +48 -8
  56. flyte/_internal/runtime/trigger_serde.py +162 -0
  57. flyte/_internal/runtime/types_serde.py +7 -16
  58. flyte/_keyring/file.py +115 -0
  59. flyte/_link.py +30 -0
  60. flyte/_logging.py +241 -42
  61. flyte/_map.py +312 -0
  62. flyte/_metrics.py +59 -0
  63. flyte/_module.py +74 -0
  64. flyte/_pod.py +30 -0
  65. flyte/_resources.py +296 -33
  66. flyte/_retry.py +1 -7
  67. flyte/_reusable_environment.py +72 -7
  68. flyte/_run.py +461 -132
  69. flyte/_secret.py +47 -11
  70. flyte/_serve.py +333 -0
  71. flyte/_task.py +245 -56
  72. flyte/_task_environment.py +219 -97
  73. flyte/_task_plugins.py +47 -0
  74. flyte/_tools.py +8 -8
  75. flyte/_trace.py +15 -24
  76. flyte/_trigger.py +1027 -0
  77. flyte/_utils/__init__.py +12 -1
  78. flyte/_utils/asyn.py +3 -1
  79. flyte/_utils/async_cache.py +139 -0
  80. flyte/_utils/coro_management.py +5 -4
  81. flyte/_utils/description_parser.py +19 -0
  82. flyte/_utils/docker_credentials.py +173 -0
  83. flyte/_utils/helpers.py +45 -19
  84. flyte/_utils/module_loader.py +123 -0
  85. flyte/_utils/org_discovery.py +57 -0
  86. flyte/_utils/uv_script_parser.py +8 -1
  87. flyte/_version.py +16 -3
  88. flyte/app/__init__.py +27 -0
  89. flyte/app/_app_environment.py +362 -0
  90. flyte/app/_connector_environment.py +40 -0
  91. flyte/app/_deploy.py +130 -0
  92. flyte/app/_parameter.py +343 -0
  93. flyte/app/_runtime/__init__.py +3 -0
  94. flyte/app/_runtime/app_serde.py +383 -0
  95. flyte/app/_types.py +113 -0
  96. flyte/app/extras/__init__.py +9 -0
  97. flyte/app/extras/_auth_middleware.py +217 -0
  98. flyte/app/extras/_fastapi.py +93 -0
  99. flyte/app/extras/_model_loader/__init__.py +3 -0
  100. flyte/app/extras/_model_loader/config.py +7 -0
  101. flyte/app/extras/_model_loader/loader.py +288 -0
  102. flyte/cli/__init__.py +12 -0
  103. flyte/cli/_abort.py +28 -0
  104. flyte/cli/_build.py +114 -0
  105. flyte/cli/_common.py +493 -0
  106. flyte/cli/_create.py +371 -0
  107. flyte/cli/_delete.py +45 -0
  108. flyte/cli/_deploy.py +401 -0
  109. flyte/cli/_gen.py +316 -0
  110. flyte/cli/_get.py +446 -0
  111. flyte/cli/_option.py +33 -0
  112. {union/_cli → flyte/cli}/_params.py +152 -153
  113. flyte/cli/_plugins.py +209 -0
  114. flyte/cli/_prefetch.py +292 -0
  115. flyte/cli/_run.py +690 -0
  116. flyte/cli/_serve.py +338 -0
  117. flyte/cli/_update.py +86 -0
  118. flyte/cli/_user.py +20 -0
  119. flyte/cli/main.py +246 -0
  120. flyte/config/__init__.py +3 -0
  121. flyte/config/_config.py +248 -0
  122. flyte/config/_internal.py +73 -0
  123. flyte/config/_reader.py +225 -0
  124. flyte/connectors/__init__.py +11 -0
  125. flyte/connectors/_connector.py +330 -0
  126. flyte/connectors/_server.py +194 -0
  127. flyte/connectors/utils.py +159 -0
  128. flyte/errors.py +134 -2
  129. flyte/extend.py +24 -0
  130. flyte/extras/_container.py +69 -56
  131. flyte/git/__init__.py +3 -0
  132. flyte/git/_config.py +279 -0
  133. flyte/io/__init__.py +8 -1
  134. flyte/io/{structured_dataset → _dataframe}/__init__.py +32 -30
  135. flyte/io/{structured_dataset → _dataframe}/basic_dfs.py +75 -68
  136. flyte/io/{structured_dataset/structured_dataset.py → _dataframe/dataframe.py} +207 -242
  137. flyte/io/_dir.py +575 -113
  138. flyte/io/_file.py +587 -141
  139. flyte/io/_hashing_io.py +342 -0
  140. flyte/io/extend.py +7 -0
  141. flyte/models.py +635 -0
  142. flyte/prefetch/__init__.py +22 -0
  143. flyte/prefetch/_hf_model.py +563 -0
  144. flyte/remote/__init__.py +14 -3
  145. flyte/remote/_action.py +879 -0
  146. flyte/remote/_app.py +346 -0
  147. flyte/remote/_auth_metadata.py +42 -0
  148. flyte/remote/_client/_protocols.py +62 -4
  149. flyte/remote/_client/auth/_auth_utils.py +19 -0
  150. flyte/remote/_client/auth/_authenticators/base.py +8 -2
  151. flyte/remote/_client/auth/_authenticators/device_code.py +4 -5
  152. flyte/remote/_client/auth/_authenticators/factory.py +4 -0
  153. flyte/remote/_client/auth/_authenticators/passthrough.py +79 -0
  154. flyte/remote/_client/auth/_authenticators/pkce.py +17 -18
  155. flyte/remote/_client/auth/_channel.py +47 -18
  156. flyte/remote/_client/auth/_client_config.py +5 -3
  157. flyte/remote/_client/auth/_keyring.py +15 -2
  158. flyte/remote/_client/auth/_token_client.py +3 -3
  159. flyte/remote/_client/controlplane.py +206 -18
  160. flyte/remote/_common.py +66 -0
  161. flyte/remote/_data.py +107 -22
  162. flyte/remote/_logs.py +116 -33
  163. flyte/remote/_project.py +21 -19
  164. flyte/remote/_run.py +164 -631
  165. flyte/remote/_secret.py +72 -29
  166. flyte/remote/_task.py +387 -46
  167. flyte/remote/_trigger.py +368 -0
  168. flyte/remote/_user.py +43 -0
  169. flyte/report/_report.py +10 -6
  170. flyte/storage/__init__.py +13 -1
  171. flyte/storage/_config.py +237 -0
  172. flyte/storage/_parallel_reader.py +289 -0
  173. flyte/storage/_storage.py +268 -59
  174. flyte/syncify/__init__.py +56 -0
  175. flyte/syncify/_api.py +414 -0
  176. flyte/types/__init__.py +39 -0
  177. flyte/types/_interface.py +22 -7
  178. flyte/{io/pickle/transformer.py → types/_pickle.py} +37 -9
  179. flyte/types/_string_literals.py +8 -9
  180. flyte/types/_type_engine.py +230 -129
  181. flyte/types/_utils.py +1 -1
  182. flyte-2.0.0b46.data/scripts/debug.py +38 -0
  183. flyte-2.0.0b46.data/scripts/runtime.py +194 -0
  184. flyte-2.0.0b46.dist-info/METADATA +352 -0
  185. flyte-2.0.0b46.dist-info/RECORD +221 -0
  186. flyte-2.0.0b46.dist-info/entry_points.txt +8 -0
  187. flyte-2.0.0b46.dist-info/licenses/LICENSE +201 -0
  188. flyte/_api_commons.py +0 -3
  189. flyte/_cli/_common.py +0 -287
  190. flyte/_cli/_create.py +0 -42
  191. flyte/_cli/_delete.py +0 -23
  192. flyte/_cli/_deploy.py +0 -140
  193. flyte/_cli/_get.py +0 -235
  194. flyte/_cli/_run.py +0 -152
  195. flyte/_cli/main.py +0 -72
  196. flyte/_datastructures.py +0 -342
  197. flyte/_internal/controllers/pbhash.py +0 -39
  198. flyte/_protos/common/authorization_pb2.py +0 -66
  199. flyte/_protos/common/authorization_pb2.pyi +0 -108
  200. flyte/_protos/common/authorization_pb2_grpc.py +0 -4
  201. flyte/_protos/common/identifier_pb2.py +0 -71
  202. flyte/_protos/common/identifier_pb2.pyi +0 -82
  203. flyte/_protos/common/identifier_pb2_grpc.py +0 -4
  204. flyte/_protos/common/identity_pb2.py +0 -48
  205. flyte/_protos/common/identity_pb2.pyi +0 -72
  206. flyte/_protos/common/identity_pb2_grpc.py +0 -4
  207. flyte/_protos/common/list_pb2.py +0 -36
  208. flyte/_protos/common/list_pb2.pyi +0 -69
  209. flyte/_protos/common/list_pb2_grpc.py +0 -4
  210. flyte/_protos/common/policy_pb2.py +0 -37
  211. flyte/_protos/common/policy_pb2.pyi +0 -27
  212. flyte/_protos/common/policy_pb2_grpc.py +0 -4
  213. flyte/_protos/common/role_pb2.py +0 -37
  214. flyte/_protos/common/role_pb2.pyi +0 -53
  215. flyte/_protos/common/role_pb2_grpc.py +0 -4
  216. flyte/_protos/common/runtime_version_pb2.py +0 -28
  217. flyte/_protos/common/runtime_version_pb2.pyi +0 -24
  218. flyte/_protos/common/runtime_version_pb2_grpc.py +0 -4
  219. flyte/_protos/logs/dataplane/payload_pb2.py +0 -96
  220. flyte/_protos/logs/dataplane/payload_pb2.pyi +0 -168
  221. flyte/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  222. flyte/_protos/secret/definition_pb2.py +0 -49
  223. flyte/_protos/secret/definition_pb2.pyi +0 -93
  224. flyte/_protos/secret/definition_pb2_grpc.py +0 -4
  225. flyte/_protos/secret/payload_pb2.py +0 -62
  226. flyte/_protos/secret/payload_pb2.pyi +0 -94
  227. flyte/_protos/secret/payload_pb2_grpc.py +0 -4
  228. flyte/_protos/secret/secret_pb2.py +0 -38
  229. flyte/_protos/secret/secret_pb2.pyi +0 -6
  230. flyte/_protos/secret/secret_pb2_grpc.py +0 -198
  231. flyte/_protos/secret/secret_pb2_grpc_grpc.py +0 -198
  232. flyte/_protos/validate/validate/validate_pb2.py +0 -76
  233. flyte/_protos/workflow/node_execution_service_pb2.py +0 -26
  234. flyte/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  235. flyte/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  236. flyte/_protos/workflow/queue_service_pb2.py +0 -106
  237. flyte/_protos/workflow/queue_service_pb2.pyi +0 -141
  238. flyte/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  239. flyte/_protos/workflow/run_definition_pb2.py +0 -128
  240. flyte/_protos/workflow/run_definition_pb2.pyi +0 -310
  241. flyte/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  242. flyte/_protos/workflow/run_logs_service_pb2.py +0 -41
  243. flyte/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  244. flyte/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  245. flyte/_protos/workflow/run_service_pb2.py +0 -133
  246. flyte/_protos/workflow/run_service_pb2.pyi +0 -175
  247. flyte/_protos/workflow/run_service_pb2_grpc.py +0 -412
  248. flyte/_protos/workflow/state_service_pb2.py +0 -58
  249. flyte/_protos/workflow/state_service_pb2.pyi +0 -71
  250. flyte/_protos/workflow/state_service_pb2_grpc.py +0 -138
  251. flyte/_protos/workflow/task_definition_pb2.py +0 -72
  252. flyte/_protos/workflow/task_definition_pb2.pyi +0 -65
  253. flyte/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  254. flyte/_protos/workflow/task_service_pb2.py +0 -44
  255. flyte/_protos/workflow/task_service_pb2.pyi +0 -31
  256. flyte/_protos/workflow/task_service_pb2_grpc.py +0 -104
  257. flyte/io/_dataframe.py +0 -0
  258. flyte/io/pickle/__init__.py +0 -0
  259. flyte/remote/_console.py +0 -18
  260. flyte-0.0.1b0.dist-info/METADATA +0 -179
  261. flyte-0.0.1b0.dist-info/RECORD +0 -390
  262. flyte-0.0.1b0.dist-info/entry_points.txt +0 -3
  263. union/__init__.py +0 -54
  264. union/_api_commons.py +0 -3
  265. union/_bin/__init__.py +0 -0
  266. union/_bin/runtime.py +0 -113
  267. union/_build.py +0 -25
  268. union/_cache/__init__.py +0 -12
  269. union/_cache/cache.py +0 -141
  270. union/_cache/defaults.py +0 -9
  271. union/_cache/policy_function_body.py +0 -42
  272. union/_cli/__init__.py +0 -0
  273. union/_cli/_common.py +0 -263
  274. union/_cli/_create.py +0 -40
  275. union/_cli/_delete.py +0 -23
  276. union/_cli/_deploy.py +0 -120
  277. union/_cli/_get.py +0 -162
  278. union/_cli/_run.py +0 -150
  279. union/_cli/main.py +0 -72
  280. union/_code_bundle/__init__.py +0 -8
  281. union/_code_bundle/_ignore.py +0 -113
  282. union/_code_bundle/_packaging.py +0 -187
  283. union/_code_bundle/_utils.py +0 -342
  284. union/_code_bundle/bundle.py +0 -176
  285. union/_context.py +0 -146
  286. union/_datastructures.py +0 -295
  287. union/_deploy.py +0 -185
  288. union/_doc.py +0 -29
  289. union/_docstring.py +0 -26
  290. union/_environment.py +0 -43
  291. union/_group.py +0 -31
  292. union/_hash.py +0 -23
  293. union/_image.py +0 -760
  294. union/_initialize.py +0 -585
  295. union/_interface.py +0 -84
  296. union/_internal/__init__.py +0 -3
  297. union/_internal/controllers/__init__.py +0 -77
  298. union/_internal/controllers/_local_controller.py +0 -77
  299. union/_internal/controllers/pbhash.py +0 -39
  300. union/_internal/controllers/remote/__init__.py +0 -40
  301. union/_internal/controllers/remote/_action.py +0 -131
  302. union/_internal/controllers/remote/_client.py +0 -43
  303. union/_internal/controllers/remote/_controller.py +0 -169
  304. union/_internal/controllers/remote/_core.py +0 -341
  305. union/_internal/controllers/remote/_informer.py +0 -260
  306. union/_internal/controllers/remote/_service_protocol.py +0 -44
  307. union/_internal/imagebuild/__init__.py +0 -11
  308. union/_internal/imagebuild/docker_builder.py +0 -416
  309. union/_internal/imagebuild/image_builder.py +0 -243
  310. union/_internal/imagebuild/remote_builder.py +0 -0
  311. union/_internal/resolvers/__init__.py +0 -0
  312. union/_internal/resolvers/_task_module.py +0 -31
  313. union/_internal/resolvers/common.py +0 -24
  314. union/_internal/resolvers/default.py +0 -27
  315. union/_internal/runtime/__init__.py +0 -0
  316. union/_internal/runtime/convert.py +0 -163
  317. union/_internal/runtime/entrypoints.py +0 -121
  318. union/_internal/runtime/io.py +0 -136
  319. union/_internal/runtime/resources_serde.py +0 -134
  320. union/_internal/runtime/task_serde.py +0 -202
  321. union/_internal/runtime/taskrunner.py +0 -179
  322. union/_internal/runtime/types_serde.py +0 -53
  323. union/_logging.py +0 -124
  324. union/_protos/__init__.py +0 -0
  325. union/_protos/common/authorization_pb2.py +0 -66
  326. union/_protos/common/authorization_pb2.pyi +0 -106
  327. union/_protos/common/authorization_pb2_grpc.py +0 -4
  328. union/_protos/common/identifier_pb2.py +0 -71
  329. union/_protos/common/identifier_pb2.pyi +0 -82
  330. union/_protos/common/identifier_pb2_grpc.py +0 -4
  331. union/_protos/common/identity_pb2.py +0 -48
  332. union/_protos/common/identity_pb2.pyi +0 -72
  333. union/_protos/common/identity_pb2_grpc.py +0 -4
  334. union/_protos/common/list_pb2.py +0 -36
  335. union/_protos/common/list_pb2.pyi +0 -69
  336. union/_protos/common/list_pb2_grpc.py +0 -4
  337. union/_protos/common/policy_pb2.py +0 -37
  338. union/_protos/common/policy_pb2.pyi +0 -27
  339. union/_protos/common/policy_pb2_grpc.py +0 -4
  340. union/_protos/common/role_pb2.py +0 -37
  341. union/_protos/common/role_pb2.pyi +0 -51
  342. union/_protos/common/role_pb2_grpc.py +0 -4
  343. union/_protos/common/runtime_version_pb2.py +0 -28
  344. union/_protos/common/runtime_version_pb2.pyi +0 -24
  345. union/_protos/common/runtime_version_pb2_grpc.py +0 -4
  346. union/_protos/logs/dataplane/payload_pb2.py +0 -96
  347. union/_protos/logs/dataplane/payload_pb2.pyi +0 -168
  348. union/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  349. union/_protos/secret/definition_pb2.py +0 -49
  350. union/_protos/secret/definition_pb2.pyi +0 -93
  351. union/_protos/secret/definition_pb2_grpc.py +0 -4
  352. union/_protos/secret/payload_pb2.py +0 -62
  353. union/_protos/secret/payload_pb2.pyi +0 -94
  354. union/_protos/secret/payload_pb2_grpc.py +0 -4
  355. union/_protos/secret/secret_pb2.py +0 -38
  356. union/_protos/secret/secret_pb2.pyi +0 -6
  357. union/_protos/secret/secret_pb2_grpc.py +0 -198
  358. union/_protos/validate/validate/validate_pb2.py +0 -76
  359. union/_protos/workflow/node_execution_service_pb2.py +0 -26
  360. union/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  361. union/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  362. union/_protos/workflow/queue_service_pb2.py +0 -75
  363. union/_protos/workflow/queue_service_pb2.pyi +0 -103
  364. union/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  365. union/_protos/workflow/run_definition_pb2.py +0 -100
  366. union/_protos/workflow/run_definition_pb2.pyi +0 -256
  367. union/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  368. union/_protos/workflow/run_logs_service_pb2.py +0 -41
  369. union/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  370. union/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  371. union/_protos/workflow/run_service_pb2.py +0 -133
  372. union/_protos/workflow/run_service_pb2.pyi +0 -173
  373. union/_protos/workflow/run_service_pb2_grpc.py +0 -412
  374. union/_protos/workflow/state_service_pb2.py +0 -58
  375. union/_protos/workflow/state_service_pb2.pyi +0 -69
  376. union/_protos/workflow/state_service_pb2_grpc.py +0 -138
  377. union/_protos/workflow/task_definition_pb2.py +0 -72
  378. union/_protos/workflow/task_definition_pb2.pyi +0 -65
  379. union/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  380. union/_protos/workflow/task_service_pb2.py +0 -44
  381. union/_protos/workflow/task_service_pb2.pyi +0 -31
  382. union/_protos/workflow/task_service_pb2_grpc.py +0 -104
  383. union/_resources.py +0 -226
  384. union/_retry.py +0 -32
  385. union/_reusable_environment.py +0 -25
  386. union/_run.py +0 -374
  387. union/_secret.py +0 -61
  388. union/_task.py +0 -354
  389. union/_task_environment.py +0 -186
  390. union/_timeout.py +0 -47
  391. union/_tools.py +0 -27
  392. union/_utils/__init__.py +0 -11
  393. union/_utils/asyn.py +0 -119
  394. union/_utils/file_handling.py +0 -71
  395. union/_utils/helpers.py +0 -46
  396. union/_utils/lazy_module.py +0 -54
  397. union/_utils/uv_script_parser.py +0 -49
  398. union/_version.py +0 -21
  399. union/connectors/__init__.py +0 -0
  400. union/errors.py +0 -128
  401. union/extras/__init__.py +0 -5
  402. union/extras/_container.py +0 -263
  403. union/io/__init__.py +0 -11
  404. union/io/_dataframe.py +0 -0
  405. union/io/_dir.py +0 -425
  406. union/io/_file.py +0 -418
  407. union/io/pickle/__init__.py +0 -0
  408. union/io/pickle/transformer.py +0 -117
  409. union/io/structured_dataset/__init__.py +0 -122
  410. union/io/structured_dataset/basic_dfs.py +0 -219
  411. union/io/structured_dataset/structured_dataset.py +0 -1057
  412. union/py.typed +0 -0
  413. union/remote/__init__.py +0 -23
  414. union/remote/_client/__init__.py +0 -0
  415. union/remote/_client/_protocols.py +0 -129
  416. union/remote/_client/auth/__init__.py +0 -12
  417. union/remote/_client/auth/_authenticators/__init__.py +0 -0
  418. union/remote/_client/auth/_authenticators/base.py +0 -391
  419. union/remote/_client/auth/_authenticators/client_credentials.py +0 -73
  420. union/remote/_client/auth/_authenticators/device_code.py +0 -120
  421. union/remote/_client/auth/_authenticators/external_command.py +0 -77
  422. union/remote/_client/auth/_authenticators/factory.py +0 -200
  423. union/remote/_client/auth/_authenticators/pkce.py +0 -515
  424. union/remote/_client/auth/_channel.py +0 -184
  425. union/remote/_client/auth/_client_config.py +0 -83
  426. union/remote/_client/auth/_default_html.py +0 -32
  427. union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  428. union/remote/_client/auth/_grpc_utils/auth_interceptor.py +0 -204
  429. union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +0 -144
  430. union/remote/_client/auth/_keyring.py +0 -154
  431. union/remote/_client/auth/_token_client.py +0 -258
  432. union/remote/_client/auth/errors.py +0 -16
  433. union/remote/_client/controlplane.py +0 -86
  434. union/remote/_data.py +0 -149
  435. union/remote/_logs.py +0 -74
  436. union/remote/_project.py +0 -86
  437. union/remote/_run.py +0 -820
  438. union/remote/_secret.py +0 -132
  439. union/remote/_task.py +0 -193
  440. union/report/__init__.py +0 -3
  441. union/report/_report.py +0 -178
  442. union/report/_template.html +0 -124
  443. union/storage/__init__.py +0 -24
  444. union/storage/_remote_fs.py +0 -34
  445. union/storage/_storage.py +0 -247
  446. union/storage/_utils.py +0 -5
  447. union/types/__init__.py +0 -11
  448. union/types/_renderer.py +0 -162
  449. union/types/_string_literals.py +0 -120
  450. union/types/_type_engine.py +0 -2131
  451. union/types/_utils.py +0 -80
  452. /flyte/{_cli → _debug}/__init__.py +0 -0
  453. /flyte/{_protos → _keyring}/__init__.py +0 -0
  454. {flyte-0.0.1b0.dist-info → flyte-2.0.0b46.dist-info}/WHEEL +0 -0
  455. {flyte-0.0.1b0.dist-info → flyte-2.0.0b46.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,330 @@
1
+ import asyncio
2
+ import json
3
+ import os
4
+ import typing
5
+ from abc import ABC, abstractmethod
6
+ from dataclasses import asdict, dataclass
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ from flyteidl2.connector import connector_pb2
10
+ from flyteidl2.connector.connector_pb2 import Connector as ConnectorProto
11
+ from flyteidl2.connector.connector_pb2 import (
12
+ GetTaskLogsResponse,
13
+ GetTaskMetricsResponse,
14
+ TaskCategory,
15
+ TaskExecutionMetadata,
16
+ )
17
+ from flyteidl2.core import tasks_pb2
18
+ from flyteidl2.core.execution_pb2 import TaskExecution, TaskLog
19
+ from google.protobuf import json_format
20
+ from google.protobuf.struct_pb2 import Struct
21
+
22
+ import flyte.storage as storage
23
+ from flyte import Secret
24
+ from flyte._code_bundle import build_code_bundle
25
+ from flyte._context import internal_ctx
26
+ from flyte._deploy import build_images
27
+ from flyte._initialize import get_init_config
28
+ from flyte._internal.runtime import convert, io
29
+ from flyte._internal.runtime.convert import convert_from_native_to_inputs, convert_from_native_to_outputs
30
+ from flyte._internal.runtime.io import upload_inputs
31
+ from flyte._internal.runtime.task_serde import get_proto_task
32
+ from flyte._logging import logger
33
+ from flyte._task import AsyncFunctionTaskTemplate, TaskTemplate
34
+ from flyte.connectors.utils import _render_task_template, is_terminal_phase
35
+ from flyte.models import CodeBundle, NativeInterface, SerializationContext
36
+ from flyte.types._type_engine import dataclass_from_dict
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class ConnectorRegistryKey:
41
+ task_type_name: str
42
+ task_type_version: int
43
+
44
+
45
+ @dataclass
46
+ class ResourceMeta:
47
+ """
48
+ This is the metadata for the job. For example, the id of the job.
49
+ """
50
+
51
+ def encode(self) -> bytes:
52
+ """
53
+ Encode the resource meta to bytes.
54
+ """
55
+ return json.dumps(asdict(self)).encode("utf-8")
56
+
57
+ @classmethod
58
+ def decode(cls, data: bytes) -> "ResourceMeta":
59
+ """
60
+ Decode the resource meta from bytes.
61
+ """
62
+ return dataclass_from_dict(cls, json.loads(data.decode("utf-8")))
63
+
64
+
65
+ @dataclass
66
+ class Resource:
67
+ """
68
+ This is the output resource of the job.
69
+
70
+ Attributes
71
+ ----------
72
+ phase : TaskExecution.Phase
73
+ The phase of the job.
74
+ message : Optional[str]
75
+ The return message from the job.
76
+ log_links : Optional[List[TaskLog]]
77
+ The log links of the job. For example, the link to the BigQuery Console.
78
+ outputs : Optional[Union[LiteralMap, typing.Dict[str, Any]]]
79
+ The outputs of the job. If return python native types, the agent will convert them to flyte literals.
80
+ custom_info : Optional[typing.Dict[str, Any]]
81
+ The custom info of the job. For example, the job config.
82
+ """
83
+
84
+ phase: TaskExecution.Phase
85
+ message: Optional[str] = None
86
+ log_links: Optional[List[TaskLog]] = None
87
+ outputs: Optional[Dict[str, Any]] = None
88
+ custom_info: Optional[typing.Dict[str, Any]] = None
89
+
90
+
91
+ class AsyncConnector(ABC):
92
+ """
93
+ This is the base class for all async connectors, and it defines the interface that all connectors must implement.
94
+ The connector service is responsible for invoking connectors.
95
+ The executor will communicate with the connector service to create tasks, get the status of tasks, and delete tasks.
96
+
97
+ All the connectors should be registered in the ConnectorRegistry.
98
+ Connector Service will look up the connector based on the task type and version.
99
+ """
100
+
101
+ name = "Async Connector"
102
+ task_type_name: str
103
+ task_type_version: int = 0
104
+ metadata_type: ResourceMeta
105
+
106
+ @abstractmethod
107
+ async def create(
108
+ self,
109
+ task_template: tasks_pb2.TaskTemplate,
110
+ output_prefix: str,
111
+ inputs: Optional[Dict[str, typing.Any]] = None,
112
+ task_execution_metadata: Optional[TaskExecutionMetadata] = None,
113
+ **kwargs,
114
+ ) -> ResourceMeta:
115
+ """
116
+ Return a resource meta that can be used to get the status of the task.
117
+ """
118
+ raise NotImplementedError
119
+
120
+ @abstractmethod
121
+ async def get(self, resource_meta: ResourceMeta, **kwargs) -> Resource:
122
+ """
123
+ Return the status of the task, and return the outputs in some cases. For example, bigquery job
124
+ can't write the structured dataset to the output location, so it returns the output literals to the propeller,
125
+ and the propeller will write the structured dataset to the blob store.
126
+ """
127
+ raise NotImplementedError
128
+
129
+ @abstractmethod
130
+ async def delete(self, resource_meta: ResourceMeta, **kwargs):
131
+ """
132
+ Delete the task. This call should be idempotent. It should raise an error if fails to delete the task.
133
+ """
134
+ raise NotImplementedError
135
+
136
+ async def get_metrics(self, resource_meta: ResourceMeta, **kwargs) -> GetTaskMetricsResponse:
137
+ """
138
+ Return the metrics for the task.
139
+ """
140
+ raise NotImplementedError
141
+
142
+ async def get_logs(self, resource_meta: ResourceMeta, **kwargs) -> GetTaskLogsResponse:
143
+ """
144
+ Return the metrics for the task.
145
+ """
146
+ raise NotImplementedError
147
+
148
+
149
+ class ConnectorRegistry(object):
150
+ """
151
+ This is the registry for all connectors.
152
+ The connector service will look up the connector registry based on the task type and version.
153
+ """
154
+
155
+ _REGISTRY: typing.ClassVar[Dict[ConnectorRegistryKey, AsyncConnector]] = {}
156
+ _METADATA: typing.ClassVar[Dict[str, ConnectorProto]] = {}
157
+
158
+ @staticmethod
159
+ def register(connector: AsyncConnector, override: bool = False):
160
+ key = ConnectorRegistryKey(
161
+ task_type_name=connector.task_type_name, task_type_version=connector.task_type_version
162
+ )
163
+ if key in ConnectorRegistry._REGISTRY and override is False:
164
+ raise ValueError(
165
+ f"Duplicate connector for task type: {connector.task_type_name}"
166
+ f" and version: {connector.task_type_version}"
167
+ )
168
+ ConnectorRegistry._REGISTRY[key] = connector
169
+
170
+ task_category = TaskCategory(name=connector.task_type_name, version=connector.task_type_version)
171
+
172
+ if connector.name in ConnectorRegistry._METADATA:
173
+ connector_metadata = ConnectorRegistry._get_connector_metadata(connector.name)
174
+ connector_metadata.supported_task_categories.append(task_category)
175
+ else:
176
+ connector_metadata = ConnectorProto(
177
+ name=connector.name,
178
+ supported_task_categories=[task_category],
179
+ )
180
+ ConnectorRegistry._METADATA[connector.name] = connector_metadata
181
+
182
+ @staticmethod
183
+ def get_connector(task_type_name: str, task_type_version: int = 0) -> AsyncConnector:
184
+ key = ConnectorRegistryKey(task_type_name=task_type_name, task_type_version=task_type_version)
185
+ if key not in ConnectorRegistry._REGISTRY:
186
+ raise FlyteConnectorNotFound(
187
+ f"Cannot find connector for task type: {task_type_name} and version: {task_type_version}"
188
+ )
189
+ return ConnectorRegistry._REGISTRY[key]
190
+
191
+ @staticmethod
192
+ def _list_connectors() -> List[ConnectorProto]:
193
+ return list(ConnectorRegistry._METADATA.values())
194
+
195
+ @staticmethod
196
+ def _get_connector_metadata(name: str) -> ConnectorProto:
197
+ if name not in ConnectorRegistry._METADATA:
198
+ raise FlyteConnectorNotFound(f"Cannot find connector for name: {name}.")
199
+ return ConnectorRegistry._METADATA[name]
200
+
201
+
202
+ class ConnectorSecretsMixin:
203
+ def __init__(self, secrets: Dict[str, str]):
204
+ # Key is the id of the secret, value is the secret name.
205
+ self._secrets = secrets
206
+
207
+ @property
208
+ def secrets(self) -> List[Secret]:
209
+ return [Secret(key=k, as_env_var=v) for k, v in self._secrets.items()]
210
+
211
+
212
+ class AsyncConnectorExecutorMixin:
213
+ """
214
+ This mixin class is used to run the connector task locally, and it's only used for local execution.
215
+ Task should inherit from this class if the task can be run in the connector.
216
+ """
217
+
218
+ async def execute(self, **kwargs) -> Any:
219
+ task = typing.cast(TaskTemplate, self)
220
+ connector = ConnectorRegistry.get_connector(task.task_type, task.task_type_version)
221
+
222
+ ctx = internal_ctx()
223
+ tctx = internal_ctx().data.task_context
224
+ cfg = get_init_config()
225
+
226
+ if tctx is None:
227
+ raise RuntimeError("Task context is not set.")
228
+
229
+ if tctx.mode == "remote" and isinstance(self, AsyncFunctionTaskTemplate):
230
+ return await AsyncFunctionTaskTemplate.execute(self, **kwargs)
231
+
232
+ prefix = tctx.raw_data_path.get_random_remote_path()
233
+ if isinstance(self, AsyncFunctionTaskTemplate):
234
+ if not storage.is_remote(tctx.raw_data_path.path):
235
+ return await TaskTemplate.execute(self, **kwargs)
236
+ else:
237
+ local_code_bundle = await build_code_bundle(
238
+ from_dir=cfg.root_dir,
239
+ dryrun=True,
240
+ )
241
+ if local_code_bundle.tgz is None:
242
+ raise RuntimeError("no tgz found in code bundle")
243
+ remote_code_path = await storage.put(
244
+ local_code_bundle.tgz, prefix + "/code_bundle/" + os.path.basename(local_code_bundle.tgz)
245
+ )
246
+ sc = SerializationContext(
247
+ project=tctx.action.project,
248
+ domain=tctx.action.domain,
249
+ org=tctx.action.org,
250
+ code_bundle=CodeBundle(
251
+ tgz=remote_code_path,
252
+ computed_version=local_code_bundle.computed_version,
253
+ destination="/opt/flyte/",
254
+ ),
255
+ version=tctx.version,
256
+ image_cache=await build_images.aio(task.parent_env()) if task.parent_env else None,
257
+ root_dir=cfg.root_dir,
258
+ )
259
+ tt = get_proto_task(task, sc)
260
+
261
+ tt = _render_task_template(tt, prefix)
262
+ inputs = await convert_from_native_to_inputs(task.native_interface, **kwargs)
263
+ inputs_uri = io.inputs_path(prefix)
264
+ await upload_inputs(inputs, inputs_uri)
265
+ else:
266
+ sc = SerializationContext(
267
+ project=tctx.action.project,
268
+ domain=tctx.action.domain,
269
+ org=tctx.action.org,
270
+ code_bundle=tctx.code_bundle,
271
+ version=tctx.version,
272
+ image_cache=tctx.compiled_image_cache,
273
+ root_dir=cfg.root_dir,
274
+ )
275
+ tt = get_proto_task(task, sc)
276
+
277
+ custom = json_format.MessageToDict(tt.custom)
278
+ secrets = custom["secrets"] if "secrets" in custom else {}
279
+ for k, v in secrets.items():
280
+ env_var = os.getenv(v)
281
+ if env_var is None:
282
+ raise ValueError(f"Secret {v} not found in environment.")
283
+ secrets[k] = env_var
284
+ resource_meta = await connector.create(
285
+ task_template=tt, output_prefix=ctx.raw_data.path, inputs=kwargs, **secrets
286
+ )
287
+ resource = Resource(phase=TaskExecution.RUNNING)
288
+
289
+ while not is_terminal_phase(resource.phase):
290
+ resource = await connector.get(resource_meta=resource_meta, **secrets)
291
+
292
+ if resource.log_links:
293
+ for link in resource.log_links:
294
+ logger.info(f"{link.name}: {link.uri}")
295
+ await asyncio.sleep(3)
296
+
297
+ if resource.phase != TaskExecution.SUCCEEDED:
298
+ raise RuntimeError(f"Failed to run the task {task.name} with error: {resource.message}")
299
+
300
+ # TODO: Support abort
301
+ if (
302
+ isinstance(self, AsyncFunctionTaskTemplate)
303
+ and storage.is_remote(tctx.raw_data_path.path)
304
+ and await storage.exists(io.outputs_path(prefix))
305
+ ):
306
+ outputs = await io.load_outputs(io.outputs_path(prefix))
307
+ return await convert.convert_outputs_to_native(task.interface, outputs)
308
+
309
+ if resource.outputs is None:
310
+ return None
311
+ return tuple(resource.outputs.values())
312
+
313
+
314
+ async def get_resource_proto(resource: Resource) -> connector_pb2.Resource:
315
+ if resource.outputs:
316
+ interface = NativeInterface.from_types(inputs={}, outputs={k: type(v) for k, v in resource.outputs.items()})
317
+ outputs = (await convert_from_native_to_outputs(tuple(resource.outputs.values()), interface)).proto_outputs
318
+ else:
319
+ outputs = None
320
+
321
+ return connector_pb2.Resource(
322
+ phase=resource.phase,
323
+ message=resource.message,
324
+ log_links=resource.log_links,
325
+ outputs=outputs,
326
+ custom_info=(json_format.Parse(json.dumps(resource.custom_info), Struct()) if resource.custom_info else None),
327
+ )
328
+
329
+
330
+ class FlyteConnectorNotFound(ValueError): ...
@@ -0,0 +1,194 @@
1
+ import inspect
2
+ import os
3
+ import sys
4
+ from http import HTTPStatus
5
+ from typing import Callable, Dict, List, Tuple, Type, Union
6
+
7
+ import grpc
8
+ from flyteidl2.connector.connector_pb2 import (
9
+ CreateTaskRequest,
10
+ CreateTaskResponse,
11
+ DeleteTaskRequest,
12
+ DeleteTaskResponse,
13
+ GetConnectorRequest,
14
+ GetConnectorResponse,
15
+ GetTaskLogsRequest,
16
+ GetTaskLogsResponse,
17
+ GetTaskMetricsRequest,
18
+ GetTaskMetricsResponse,
19
+ GetTaskRequest,
20
+ GetTaskResponse,
21
+ ListConnectorsRequest,
22
+ ListConnectorsResponse,
23
+ )
24
+ from flyteidl2.connector.service_pb2_grpc import AsyncConnectorServiceServicer, ConnectorMetadataServiceServicer
25
+ from flyteidl2.core.security_pb2 import Connection
26
+ from prometheus_client import Counter, Summary
27
+
28
+ from flyte._internal.runtime.convert import Inputs, convert_from_inputs_to_native
29
+ from flyte._logging import logger
30
+ from flyte.connectors._connector import ConnectorRegistry, FlyteConnectorNotFound, get_resource_proto
31
+ from flyte.connectors.utils import _start_grpc_server
32
+ from flyte.models import NativeInterface, _has_default
33
+ from flyte.syncify import syncify
34
+ from flyte.types import TypeEngine
35
+
36
+ metric_prefix = "flyte_connector_"
37
+ create_operation = "create"
38
+ get_operation = "get"
39
+ delete_operation = "delete"
40
+
41
+ # Follow the naming convention. https://prometheus.io/docs/practices/naming/
42
+ request_success_count = Counter(
43
+ f"{metric_prefix}requests_success_total",
44
+ "Total number of successful requests",
45
+ ["task_type", "operation"],
46
+ )
47
+ request_failure_count = Counter(
48
+ f"{metric_prefix}requests_failure_total",
49
+ "Total number of failed requests",
50
+ ["task_type", "operation", "error_code"],
51
+ )
52
+ request_latency = Summary(
53
+ f"{metric_prefix}request_latency_seconds",
54
+ "Time spent processing connector request",
55
+ ["task_type", "operation"],
56
+ )
57
+ input_literal_size = Summary(f"{metric_prefix}input_literal_bytes", "Size of input literal", ["task_type"])
58
+
59
+
60
+ def _handle_exception(e: Exception, context: grpc.ServicerContext, task_type: str, operation: str):
61
+ if isinstance(e, FlyteConnectorNotFound):
62
+ error_message = f"Cannot find connector for task type: {task_type}."
63
+ logger.error(error_message)
64
+ context.set_code(grpc.StatusCode.NOT_FOUND)
65
+ context.set_details(error_message)
66
+ request_failure_count.labels(task_type=task_type, operation=operation, error_code=HTTPStatus.NOT_FOUND).inc()
67
+ else:
68
+ error_message = f"failed to {operation} {task_type} task with error:\n {e}."
69
+ logger.error(error_message)
70
+ context.set_code(grpc.StatusCode.INTERNAL)
71
+ context.set_details(error_message)
72
+ request_failure_count.labels(
73
+ task_type=task_type, operation=operation, error_code=HTTPStatus.INTERNAL_SERVER_ERROR
74
+ ).inc()
75
+
76
+
77
+ class ConnectorService:
78
+ @syncify
79
+ @classmethod
80
+ async def run(cls, port: int, prometheus_port: int, worker: int, timeout: int | None, modules: List[str] | None):
81
+ working_dir = os.getcwd()
82
+ if all(os.path.realpath(path) != working_dir for path in sys.path):
83
+ sys.path.append(working_dir)
84
+ await _start_grpc_server(port, prometheus_port, worker, timeout, modules)
85
+
86
+
87
+ def record_connector_metrics(func: Callable):
88
+ async def wrapper(
89
+ self,
90
+ request: Union[CreateTaskRequest, GetTaskRequest, DeleteTaskRequest],
91
+ context: grpc.ServicerContext,
92
+ *args,
93
+ **kwargs,
94
+ ):
95
+ if isinstance(request, CreateTaskRequest):
96
+ task_type = request.template.type
97
+ operation = create_operation
98
+ if request.inputs:
99
+ input_literal_size.labels(task_type=task_type).observe(request.inputs.ByteSize())
100
+ elif isinstance(request, GetTaskRequest):
101
+ task_type = request.task_category.name
102
+ operation = get_operation
103
+ elif isinstance(request, DeleteTaskRequest):
104
+ task_type = request.task_category.name
105
+ operation = delete_operation
106
+ else:
107
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
108
+ context.set_details("Method not implemented!")
109
+ return None
110
+
111
+ try:
112
+ with request_latency.labels(task_type=task_type, operation=operation).time():
113
+ res = await func(self, request, context, *args, **kwargs)
114
+ request_success_count.labels(task_type=task_type, operation=operation).inc()
115
+ return res
116
+ except Exception as e:
117
+ _handle_exception(e, context, task_type, operation)
118
+
119
+ return wrapper
120
+
121
+
122
+ def _get_connection_kwargs(request: Connection) -> Dict[str, str]:
123
+ kwargs = {}
124
+
125
+ for k, v in request.secrets.items():
126
+ kwargs[k] = v
127
+ for k, v in request.configs.items():
128
+ kwargs[k] = v
129
+
130
+ return kwargs
131
+
132
+
133
+ class AsyncConnectorService(AsyncConnectorServiceServicer):
134
+ @record_connector_metrics
135
+ async def CreateTask(self, request: CreateTaskRequest, context: grpc.ServicerContext) -> CreateTaskResponse:
136
+ template = request.template
137
+ connector = ConnectorRegistry.get_connector(template.type, template.task_type_version)
138
+ logger.info(f"{connector.name} start creating the job")
139
+ python_interface_inputs: Dict[str, Tuple[Type, Type[_has_default] | Type[inspect._empty]]] = {
140
+ name: (TypeEngine.guess_python_type(lt.type), inspect.Parameter.empty)
141
+ for name, lt in template.interface.inputs.variables.items()
142
+ }
143
+ native_interface = NativeInterface.from_types(inputs=python_interface_inputs, outputs={})
144
+ native_inputs = await convert_from_inputs_to_native(native_interface, Inputs(proto_inputs=request.inputs))
145
+ resource_meta = await connector.create(
146
+ task_template=request.template,
147
+ inputs=native_inputs,
148
+ output_prefix=request.output_prefix,
149
+ task_execution_metadata=request.task_execution_metadata,
150
+ **_get_connection_kwargs(request.connection),
151
+ )
152
+ return CreateTaskResponse(resource_meta=resource_meta.encode())
153
+
154
+ @record_connector_metrics
155
+ async def GetTask(self, request: GetTaskRequest, context: grpc.ServicerContext) -> GetTaskResponse:
156
+ connector = ConnectorRegistry.get_connector(request.task_category.name, request.task_category.version)
157
+ logger.info(f"{connector.name} start checking the status of the job")
158
+ res = await connector.get(
159
+ resource_meta=connector.metadata_type.decode(request.resource_meta),
160
+ **_get_connection_kwargs(request.connection),
161
+ )
162
+ return GetTaskResponse(resource=await get_resource_proto(res))
163
+
164
+ @record_connector_metrics
165
+ async def DeleteTask(self, request: DeleteTaskRequest, context: grpc.ServicerContext) -> DeleteTaskResponse:
166
+ connector = ConnectorRegistry.get_connector(request.task_category.name, request.task_category.version)
167
+ logger.info(f"{connector.name} start deleting the job")
168
+ await connector.delete(
169
+ resource_meta=connector.metadata_type.decode(request.resource_meta),
170
+ **_get_connection_kwargs(request.connection),
171
+ )
172
+ return DeleteTaskResponse()
173
+
174
+ async def GetTaskMetrics(
175
+ self, request: GetTaskMetricsRequest, context: grpc.ServicerContext
176
+ ) -> GetTaskMetricsResponse:
177
+ connector = ConnectorRegistry.get_connector(request.task_category.name, request.task_category.version)
178
+ logger.info(f"{connector.name} start getting metrics of the job")
179
+ return await connector.get_metrics(resource_meta=connector.metadata_type.decode(request.resource_meta))
180
+
181
+ async def GetTaskLogs(self, request: GetTaskLogsRequest, context: grpc.ServicerContext) -> GetTaskLogsResponse:
182
+ connector = ConnectorRegistry.get_connector(request.task_category.name, request.task_category.version)
183
+ logger.info(f"{connector.name} start getting logs of the job")
184
+ return await connector.get_logs(resource_meta=connector.metadata_type.decode(request.resource_meta))
185
+
186
+
187
+ class ConnectorMetadataService(ConnectorMetadataServiceServicer):
188
+ async def GetConnector(self, request: GetConnectorRequest, context: grpc.ServicerContext) -> GetConnectorResponse:
189
+ return GetConnectorResponse(connector=ConnectorRegistry._get_connector_metadata(request.name))
190
+
191
+ async def ListConnectors(
192
+ self, request: ListConnectorsRequest, context: grpc.ServicerContext
193
+ ) -> ListConnectorsResponse:
194
+ return ListConnectorsResponse(connectors=ConnectorRegistry._list_connectors())
@@ -0,0 +1,159 @@
1
+ import importlib
2
+ from concurrent import futures
3
+ from importlib.metadata import entry_points
4
+ from typing import List
5
+
6
+ import click
7
+ import grpc
8
+ from flyteidl2.connector import service_pb2
9
+ from flyteidl2.connector.service_pb2_grpc import (
10
+ add_AsyncConnectorServiceServicer_to_server,
11
+ add_ConnectorMetadataServiceServicer_to_server,
12
+ )
13
+ from flyteidl2.core.execution_pb2 import TaskExecution
14
+ from flyteidl2.core.tasks_pb2 import TaskTemplate
15
+ from rich.console import Console
16
+ from rich.table import Table
17
+
18
+ import flyte
19
+ from flyte import logger
20
+
21
+
22
+ def is_terminal_phase(phase: TaskExecution.Phase) -> bool:
23
+ """
24
+ Return true if the phase is terminal.
25
+ """
26
+ return phase in [TaskExecution.SUCCEEDED, TaskExecution.ABORTED, TaskExecution.FAILED]
27
+
28
+
29
+ def convert_to_flyte_phase(state: str) -> TaskExecution.Phase:
30
+ """
31
+ Convert the state from the connector to the phase in flyte.
32
+ """
33
+ state = state.lower()
34
+ if state in ["failed", "timeout", "timedout", "canceled", "cancelled", "skipped"]:
35
+ return TaskExecution.FAILED
36
+ if state in ["internal_error"]:
37
+ return TaskExecution.RETRYABLE_FAILED
38
+ elif state in ["done", "succeeded", "success", "completed"]:
39
+ return TaskExecution.SUCCEEDED
40
+ elif state in ["running", "terminating"]:
41
+ return TaskExecution.RUNNING
42
+ elif state in ["pending"]:
43
+ return TaskExecution.INITIALIZING
44
+ raise ValueError(f"Unrecognized state: {state}")
45
+
46
+
47
+ async def _start_grpc_server(
48
+ port: int, prometheus_port: int, worker: int, timeout: int | None, modules: List[str] | None
49
+ ):
50
+ try:
51
+ from flyte.connectors._server import (
52
+ AsyncConnectorService,
53
+ ConnectorMetadataService,
54
+ )
55
+ except ImportError as e:
56
+ raise ImportError(
57
+ "Flyte connector dependencies are not installed."
58
+ " Please install it using `pip install flyteplugins-connector`"
59
+ ) from e
60
+
61
+ click.secho("🚀 Starting the connector service...")
62
+ _load_connectors(modules)
63
+ _start_http_server(prometheus_port)
64
+
65
+ print_metadata()
66
+
67
+ server = grpc.aio.server(futures.ThreadPoolExecutor(max_workers=worker))
68
+
69
+ add_AsyncConnectorServiceServicer_to_server(AsyncConnectorService(), server)
70
+ add_ConnectorMetadataServiceServicer_to_server(ConnectorMetadataService(), server)
71
+ _start_health_check_server(server, worker)
72
+
73
+ server.add_insecure_port(f"[::]:{port}")
74
+ await server.start()
75
+ await server.wait_for_termination(timeout)
76
+
77
+
78
+ def _start_http_server(prometheus_port: int):
79
+ try:
80
+ from prometheus_client import start_http_server
81
+
82
+ click.secho("Starting up the server to expose the prometheus metrics...")
83
+ start_http_server(prometheus_port)
84
+ except ImportError as e:
85
+ click.secho(f"Failed to start the prometheus server with error {e}", fg="red")
86
+
87
+
88
+ def _start_health_check_server(server: grpc.Server, worker: int):
89
+ try:
90
+ from grpc_health.v1 import health, health_pb2, health_pb2_grpc
91
+
92
+ health_servicer = health.HealthServicer(
93
+ experimental_non_blocking=True,
94
+ experimental_thread_pool=futures.ThreadPoolExecutor(max_workers=worker),
95
+ )
96
+
97
+ for service in service_pb2.DESCRIPTOR.services_by_name.values():
98
+ health_servicer.set(service.full_name, health_pb2.HealthCheckResponse.SERVING)
99
+ health_servicer.set(health.SERVICE_NAME, health_pb2.HealthCheckResponse.SERVING)
100
+
101
+ health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
102
+
103
+ except ImportError as e:
104
+ click.secho(f"Failed to start the health check servicer with error {e}", fg="red")
105
+
106
+
107
+ def print_metadata():
108
+ from flyte.connectors import ConnectorRegistry
109
+
110
+ connectors = ConnectorRegistry._list_connectors()
111
+
112
+ table = Table(title="Connector Metadata")
113
+ table.add_column("Connector Name", style="cyan", no_wrap=True)
114
+ table.add_column("Support Task Types", style="cyan")
115
+
116
+ for connector in connectors:
117
+ categories = ""
118
+ for category in connector.supported_task_categories:
119
+ categories += f"{category.name} ({category.version}) "
120
+ table.add_row(connector.name, categories)
121
+
122
+ console = Console()
123
+ console.print(table)
124
+
125
+
126
+ def _load_connectors(modules: List[str] | None):
127
+ plugins = entry_points(group="flyte.connectors")
128
+ for ep in plugins:
129
+ try:
130
+ logger.info(f"Loading connector: {ep.name}")
131
+ ep.load()
132
+ except Exception as e:
133
+ logger.warning(f"Failed to load connector '{ep.name}' with error: {e}")
134
+
135
+ if modules:
136
+ for m in modules:
137
+ importlib.import_module(m)
138
+
139
+
140
+ def _render_task_template(tt: TaskTemplate, file_prefix: str) -> TaskTemplate:
141
+ if tt.container is None:
142
+ return tt
143
+ args = tt.container.args
144
+ ctx = flyte.ctx()
145
+ for i in range(len(args)):
146
+ tt.container.args[i] = args[i].replace("{{.input}}", f"{file_prefix}/inputs.pb")
147
+ tt.container.args[i] = args[i].replace("{{.outputPrefix}}", f"{file_prefix}")
148
+ tt.container.args[i] = args[i].replace("{{.rawOutputDataPrefix}}", f"{file_prefix}/raw_output")
149
+ tt.container.args[i] = args[i].replace("{{.checkpointOutputPrefix}}", f"{file_prefix}/checkpoint_output")
150
+ tt.container.args[i] = args[i].replace("{{.prevCheckpointPrefix}}", f"{file_prefix}/prev_checkpoint")
151
+ tt.container.args[i] = args[i].replace("{{.runName}}", ctx.action.run_name if ctx else "test-run")
152
+ tt.container.args[i] = args[i].replace("{{.actionName}}", "a1")
153
+
154
+ # Add additional required args
155
+ tt.container.args[1:1] = ["--run-base-dir", f"{file_prefix}/base_dir"]
156
+ tt.container.args[1:1] = ["--org", "test-org"]
157
+ tt.container.args[1:1] = ["--project", "test-project"]
158
+ tt.container.args[1:1] = ["--domain", "test-domain"]
159
+ return tt