flyte 0.2.0b1__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 (266) 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 -231
  26. flyte/_initialize.py +456 -316
  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 +319 -36
  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 +462 -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. flyte/{_cli → cli}/_params.py +57 -17
  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 +2 -167
  121. flyte/config/_config.py +215 -163
  122. flyte/config/_internal.py +10 -1
  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 +226 -126
  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 -299
  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 -174
  195. flyte/_cli/main.py +0 -98
  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.2.0b1.dist-info/METADATA +0 -179
  261. flyte-0.2.0b1.dist-info/RECORD +0 -204
  262. flyte-0.2.0b1.dist-info/entry_points.txt +0 -3
  263. /flyte/{_cli → _debug}/__init__.py +0 -0
  264. /flyte/{_protos → _keyring}/__init__.py +0 -0
  265. {flyte-0.2.0b1.dist-info → flyte-2.0.0b46.dist-info}/WHEEL +0 -0
  266. {flyte-0.2.0b1.dist-info → flyte-2.0.0b46.dist-info}/top_level.txt +0 -0
flyte/config/__init__.py CHANGED
@@ -1,168 +1,3 @@
1
- import os
2
- import typing
3
- from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING
1
+ from flyte.config._config import Config, auto, get_config_file, set_if_exists
5
2
 
6
- from flyte._logging import logger
7
- from flyte.config import _internal
8
- from flyte.config._config import ConfigFile, get_config_file, read_file_if_exists
9
-
10
- _all__ = ["ConfigFile", "PlatformConfig", "TaskConfig"]
11
-
12
- if TYPE_CHECKING:
13
- from flyte.remote._client.auth import AuthType
14
-
15
-
16
- @dataclass(init=True, repr=True, eq=True, frozen=True)
17
- class PlatformConfig(object):
18
- """
19
- This object contains the settings to talk to a Flyte backend (the DNS location of your Admin server basically).
20
-
21
- :param endpoint: DNS for Flyte backend
22
- :param insecure: Whether or not to use SSL
23
- :param insecure_skip_verify: Whether to skip SSL certificate verification
24
- :param console_endpoint: endpoint for console if different from Flyte backend
25
- :param command: This command is executed to return a token using an external process
26
- :param proxy_command: This command is executed to return a token for proxy authorization using an external process
27
- :param client_id: This is the public identifier for the app which handles authorization for a Flyte deployment.
28
- More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
29
- :param client_credentials_secret: Used for service auth, which is automatically called during pyflyte. This will
30
- allow the Flyte engine to read the password directly from the environment variable. Note that this is
31
- less secure! Please only use this if mounting the secret as a file is impossible
32
- :param scopes: List of scopes to request. This is only applicable to the client credentials flow
33
- :param auth_mode: The OAuth mode to use. Defaults to pkce flow
34
- :param ca_cert_file_path: [optional] str Root Cert to be loaded and used to verify admin
35
- :param http_proxy_url: [optional] HTTP Proxy to be used for OAuth requests
36
- """
37
-
38
- endpoint: str | None = None
39
- insecure: bool = False
40
- insecure_skip_verify: bool = False
41
- ca_cert_file_path: typing.Optional[str] = None
42
- console_endpoint: typing.Optional[str] = None
43
- command: typing.Optional[typing.List[str]] = None
44
- proxy_command: typing.Optional[typing.List[str]] = None
45
- client_id: typing.Optional[str] = None
46
- client_credentials_secret: typing.Optional[str] = None
47
- scopes: typing.List[str] = field(default_factory=list)
48
- auth_mode: "AuthType" = "Pkce"
49
- audience: typing.Optional[str] = None
50
- rpc_retries: int = 3
51
- http_proxy_url: typing.Optional[str] = None
52
-
53
- @classmethod
54
- def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "PlatformConfig":
55
- """
56
- Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
57
- :param config_file:
58
- :return:
59
- """
60
- from .._initialize import set_if_exists
61
-
62
- config_file = get_config_file(config_file)
63
- kwargs: typing.Dict[str, typing.Any] = {}
64
- kwargs = set_if_exists(kwargs, "insecure", _internal.Platform.INSECURE.read(config_file))
65
- kwargs = set_if_exists(
66
- kwargs, "insecure_skip_verify", _internal.Platform.INSECURE_SKIP_VERIFY.read(config_file)
67
- )
68
- kwargs = set_if_exists(kwargs, "ca_cert_file_path", _internal.Platform.CA_CERT_FILE_PATH.read(config_file))
69
- kwargs = set_if_exists(kwargs, "command", _internal.Credentials.COMMAND.read(config_file))
70
- kwargs = set_if_exists(kwargs, "proxy_command", _internal.Credentials.PROXY_COMMAND.read(config_file))
71
- kwargs = set_if_exists(kwargs, "client_id", _internal.Credentials.CLIENT_ID.read(config_file))
72
-
73
- is_client_secret = False
74
- client_credentials_secret = read_file_if_exists(
75
- _internal.Credentials.CLIENT_CREDENTIALS_SECRET_LOCATION.read(config_file)
76
- )
77
- if client_credentials_secret:
78
- is_client_secret = True
79
- if client_credentials_secret.endswith("\n"):
80
- logger.info("Newline stripped from client secret")
81
- client_credentials_secret = client_credentials_secret.strip()
82
- kwargs = set_if_exists(
83
- kwargs,
84
- "client_credentials_secret",
85
- client_credentials_secret,
86
- )
87
-
88
- client_credentials_secret_env_var = _internal.Credentials.CLIENT_CREDENTIALS_SECRET_ENV_VAR.read(config_file)
89
- if client_credentials_secret_env_var:
90
- client_credentials_secret = os.getenv(client_credentials_secret_env_var)
91
- if client_credentials_secret:
92
- is_client_secret = True
93
- kwargs = set_if_exists(kwargs, "client_credentials_secret", client_credentials_secret)
94
- kwargs = set_if_exists(kwargs, "scopes", _internal.Credentials.SCOPES.read(config_file))
95
- kwargs = set_if_exists(kwargs, "auth_mode", _internal.Credentials.AUTH_MODE.read(config_file))
96
- if is_client_secret:
97
- kwargs = set_if_exists(kwargs, "auth_mode", "ClientSecret")
98
- kwargs = set_if_exists(kwargs, "endpoint", _internal.Platform.URL.read(config_file))
99
- kwargs = set_if_exists(kwargs, "console_endpoint", _internal.Platform.CONSOLE_ENDPOINT.read(config_file))
100
-
101
- kwargs = set_if_exists(kwargs, "http_proxy_url", _internal.Platform.HTTP_PROXY_URL.read(config_file))
102
- return PlatformConfig(**kwargs)
103
-
104
- @classmethod
105
- def for_endpoint(cls, endpoint: str, insecure: bool = False) -> "PlatformConfig":
106
- return PlatformConfig(endpoint=endpoint, insecure=insecure)
107
-
108
-
109
- @dataclass(init=True, repr=True, eq=True, frozen=True)
110
- class TaskConfig(object):
111
- org: str | None = None
112
- project: str | None = None
113
- domain: str | None = None
114
-
115
- @classmethod
116
- def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "TaskConfig":
117
- """
118
- Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
119
- :param config_file:
120
- :return:
121
- """
122
- from flyte._initialize import set_if_exists
123
-
124
- config_file = get_config_file(config_file)
125
- kwargs: typing.Dict[str, typing.Any] = {}
126
- kwargs = set_if_exists(kwargs, "org", _internal.Task.ORG.read(config_file))
127
- kwargs = set_if_exists(kwargs, "project", _internal.Task.PROJECT.read(config_file))
128
- kwargs = set_if_exists(kwargs, "domain", _internal.Task.DOMAIN.read(config_file))
129
- return TaskConfig(**kwargs)
130
-
131
-
132
- @dataclass(init=True, repr=True, eq=True, frozen=True)
133
- class Config(object):
134
- """
135
- This the parent configuration object and holds all the underlying configuration object types. An instance of
136
- this object holds all the config necessary to
137
-
138
- 1. Interactive session with Flyte backend
139
- 2. Some parts are required for Serialization, for example Platform Config is not required
140
- 3. Runtime of a task
141
- """
142
-
143
- platform: PlatformConfig = field(default=PlatformConfig())
144
- task: TaskConfig = field(default=TaskConfig())
145
-
146
- def with_params(
147
- self,
148
- platform: PlatformConfig | None = None,
149
- task: TaskConfig | None = None,
150
- ) -> "Config":
151
- return Config(
152
- platform=platform or self.platform,
153
- task=task or self.task,
154
- )
155
-
156
- @classmethod
157
- def auto(cls, config_file: typing.Union[str, ConfigFile, None] = None) -> "Config":
158
- """
159
- Automatically constructs the Config Object. The order of precedence is as follows
160
- 1. first try to find any env vars that match the config vars specified in the FLYTE_CONFIG format.
161
- 2. If not found in environment then values ar read from the config file
162
- 3. If not found in the file, then the default values are used.
163
-
164
- :param config_file: file path to read the config from, if not specified default locations are searched
165
- :return: Config
166
- """
167
- config_file = get_config_file(config_file)
168
- return Config(platform=PlatformConfig.auto(config_file), task=TaskConfig.auto(config_file))
3
+ __all__ = ["Config", "auto", "get_config_file", "set_if_exists"]
flyte/config/_config.py CHANGED
@@ -1,196 +1,248 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
1
4
  import os
2
5
  import pathlib
3
6
  import typing
4
- from dataclasses import dataclass
5
- from functools import lru_cache
6
- from os import getenv
7
- from pathlib import Path
7
+ from dataclasses import dataclass, field
8
+ from typing import TYPE_CHECKING
8
9
 
9
- import yaml
10
+ import rich.repr
10
11
 
11
12
  from flyte._logging import logger
13
+ from flyte.config import _internal
14
+ from flyte.config._reader import ConfigFile, get_config_file, read_file_if_exists
15
+
16
+ _all__ = ["ConfigFile", "PlatformConfig", "TaskConfig", "ImageConfig"]
12
17
 
13
- # This is the default config file name for flyte
14
- FLYTECTL_CONFIG_ENV_VAR = "FLYTECTL_CONFIG"
15
- UCTL_CONFIG_ENV_VAR = "UCTL_CONFIG"
18
+ if TYPE_CHECKING:
19
+ from flyte.remote._client.auth import AuthType
16
20
 
17
21
 
18
- @dataclass
19
- class YamlConfigEntry(object):
22
+ @rich.repr.auto
23
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
24
+ class PlatformConfig(object):
20
25
  """
21
- Creates a record for the config entry.
22
- Args:
23
- switch: dot-delimited string that should match flytectl args. Leaving it as dot-delimited instead of a list
24
- of strings because it's easier to maintain alignment with flytectl.
25
- config_value_type: Expected type of the value
26
+ This object contains the settings to talk to a Flyte backend (the DNS location of your Admin server basically).
27
+
28
+ :param endpoint: DNS for Flyte backend
29
+ :param insecure: Whether or not to use SSL
30
+ :param insecure_skip_verify: Whether to skip SSL certificate verification
31
+ :param console_endpoint: endpoint for console if different from Flyte backend
32
+ :param command: This command is executed to return a token using an external process
33
+ :param proxy_command: This command is executed to return a token for proxy authorization using an external process
34
+ :param client_id: This is the public identifier for the app which handles authorization for a Flyte deployment.
35
+ More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
36
+ :param client_credentials_secret: Used for service auth, which is automatically called during pyflyte. This will
37
+ allow the Flyte engine to read the password directly from the environment variable. Note that this is
38
+ less secure! Please only use this if mounting the secret as a file is impossible
39
+ :param scopes: List of scopes to request. This is only applicable to the client credentials flow
40
+ :param auth_mode: The OAuth mode to use. Defaults to pkce flow
41
+ :param ca_cert_file_path: [optional] str Root Cert to be loaded and used to verify admin
42
+ :param http_proxy_url: [optional] HTTP Proxy to be used for OAuth requests
26
43
  """
27
44
 
28
- switch: str
29
- config_value_type: typing.Type = str
45
+ endpoint: str | None = None
46
+ insecure: bool = False
47
+ insecure_skip_verify: bool = False
48
+ ca_cert_file_path: typing.Optional[str] = None
49
+ console_endpoint: typing.Optional[str] = None
50
+ command: typing.Optional[typing.List[str]] = None
51
+ proxy_command: typing.Optional[typing.List[str]] = None
52
+ client_id: typing.Optional[str] = None
53
+ client_credentials_secret: typing.Optional[str] = None
54
+ scopes: typing.List[str] = field(default_factory=list)
55
+ auth_mode: "AuthType" = "Pkce"
56
+ audience: typing.Optional[str] = None
57
+ rpc_retries: int = 3
58
+ http_proxy_url: typing.Optional[str] = None
59
+
60
+ @classmethod
61
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "PlatformConfig":
62
+ """
63
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
64
+ :param config_file:
65
+ :return:
66
+ """
67
+
68
+ config_file = get_config_file(config_file)
69
+ kwargs: typing.Dict[str, typing.Any] = {}
70
+ kwargs = set_if_exists(kwargs, "insecure", _internal.Platform.INSECURE.read(config_file))
71
+ kwargs = set_if_exists(
72
+ kwargs, "insecure_skip_verify", _internal.Platform.INSECURE_SKIP_VERIFY.read(config_file)
73
+ )
74
+ kwargs = set_if_exists(kwargs, "ca_cert_file_path", _internal.Platform.CA_CERT_FILE_PATH.read(config_file))
75
+ kwargs = set_if_exists(kwargs, "command", _internal.Credentials.COMMAND.read(config_file))
76
+ kwargs = set_if_exists(kwargs, "proxy_command", _internal.Credentials.PROXY_COMMAND.read(config_file))
77
+ kwargs = set_if_exists(kwargs, "client_id", _internal.Credentials.CLIENT_ID.read(config_file))
78
+
79
+ is_client_secret = False
80
+ client_credentials_secret = read_file_if_exists(
81
+ _internal.Credentials.CLIENT_CREDENTIALS_SECRET_LOCATION.read(config_file)
82
+ )
83
+ if client_credentials_secret:
84
+ is_client_secret = True
85
+ if client_credentials_secret.endswith("\n"):
86
+ logger.info("Newline stripped from client secret")
87
+ client_credentials_secret = client_credentials_secret.strip()
88
+ kwargs = set_if_exists(
89
+ kwargs,
90
+ "client_credentials_secret",
91
+ client_credentials_secret,
92
+ )
93
+
94
+ client_credentials_secret_env_var = _internal.Credentials.CLIENT_CREDENTIALS_SECRET_ENV_VAR.read(config_file)
95
+ if client_credentials_secret_env_var:
96
+ client_credentials_secret = os.getenv(client_credentials_secret_env_var)
97
+ if client_credentials_secret:
98
+ is_client_secret = True
99
+ kwargs = set_if_exists(kwargs, "client_credentials_secret", client_credentials_secret)
100
+ kwargs = set_if_exists(kwargs, "scopes", _internal.Credentials.SCOPES.read(config_file))
101
+ kwargs = set_if_exists(kwargs, "auth_mode", _internal.Credentials.AUTH_MODE.read(config_file))
102
+ if is_client_secret:
103
+ kwargs = set_if_exists(kwargs, "auth_mode", "ClientSecret")
104
+ kwargs = set_if_exists(kwargs, "endpoint", _internal.Platform.URL.read(config_file))
105
+ kwargs = set_if_exists(kwargs, "console_endpoint", _internal.Platform.CONSOLE_ENDPOINT.read(config_file))
106
+
107
+ kwargs = set_if_exists(kwargs, "http_proxy_url", _internal.Platform.HTTP_PROXY_URL.read(config_file))
108
+ return PlatformConfig(**kwargs)
109
+
110
+ def replace(self, **kwargs: typing.Any) -> "PlatformConfig":
111
+ """
112
+ Returns a new PlatformConfig instance with the values from the kwargs overriding the current instance.
113
+ """
114
+ return dataclasses.replace(self, **kwargs)
115
+
116
+ @classmethod
117
+ def for_endpoint(cls, endpoint: str, insecure: bool = False) -> "PlatformConfig":
118
+ return PlatformConfig(endpoint=endpoint, insecure=insecure)
30
119
 
31
- def get_env_name(self) -> str:
32
- var_name = self.switch.upper().replace(".", "_")
33
- return f"FLYTE_{var_name}"
34
120
 
35
- def read_from_env(self, transform: typing.Optional[typing.Callable] = None) -> typing.Optional[typing.Any]:
121
+ @rich.repr.auto
122
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
123
+ class TaskConfig(object):
124
+ org: str | None = None
125
+ project: str | None = None
126
+ domain: str | None = None
127
+
128
+ @classmethod
129
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "TaskConfig":
36
130
  """
37
- Reads the config entry from environment variable, the structure of the env var is current
38
- ``FLYTE_{SECTION}_{OPTION}`` all upper cased. We will change this in the future.
131
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
132
+ :param config_file:
39
133
  :return:
40
134
  """
41
- env = self.get_env_name()
42
- v = os.environ.get(env, None)
43
- if v is None:
44
- return None
45
- return transform(v) if transform else v
46
-
47
- def read_from_file(
48
- self, cfg: "ConfigFile", transform: typing.Optional[typing.Callable] = None
49
- ) -> typing.Optional[typing.Any]:
50
- if not cfg:
51
- return None
52
- try:
53
- v = cfg.get(self)
54
- if isinstance(v, bool) or bool(v is not None and v):
55
- return transform(v) if transform else v
56
- except Exception:
57
- ...
58
-
59
- return None
60
-
61
-
62
- @dataclass
63
- class ConfigEntry(object):
135
+ config_file = get_config_file(config_file)
136
+ kwargs: typing.Dict[str, typing.Any] = {}
137
+ kwargs = set_if_exists(kwargs, "org", _internal.Task.ORG.read(config_file))
138
+ kwargs = set_if_exists(kwargs, "project", _internal.Task.PROJECT.read(config_file))
139
+ kwargs = set_if_exists(kwargs, "domain", _internal.Task.DOMAIN.read(config_file))
140
+ return TaskConfig(**kwargs)
141
+
142
+
143
+ @rich.repr.auto
144
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
145
+ class ImageConfig(object):
64
146
  """
65
- A top level Config entry holder, that holds multiple different representations of the config.
66
- Legacy means the INI style config files. YAML support is for the flytectl config file, which is there by default
67
- when flytectl starts a sandbox
147
+ Configuration for Docker image settings.
68
148
  """
69
149
 
70
- yaml_entry: YamlConfigEntry
71
- transform: typing.Optional[typing.Callable[[str], typing.Any]] = None
150
+ builder: str | None = None
151
+ image_refs: typing.Dict[str, str] = field(default_factory=dict)
72
152
 
73
- def read(self, cfg: typing.Optional["ConfigFile"] = None) -> typing.Optional[typing.Any]:
153
+ @classmethod
154
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "ImageConfig":
74
155
  """
75
- Reads the config Entry from the various sources in the following order,
76
- #. First try to read from the relevant environment variable,
77
- #. If missing, then try to read from the legacy config file, if one was parsed.
78
- #. If missing, then try to read from the yaml file.
79
-
80
- The constructor for ConfigFile currently does not allow specification of both the ini and yaml style formats.
81
-
82
- :param cfg:
156
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
157
+ :param config_file:
83
158
  :return:
84
159
  """
85
- from_env = self.yaml_entry.read_from_env(self.transform)
86
- if from_env is not None:
87
- return from_env
88
- if cfg and cfg.yaml_config and self.yaml_entry:
89
- return self.yaml_entry.read_from_file(cfg, self.transform)
160
+ config_file = get_config_file(config_file)
161
+ kwargs: typing.Dict[str, typing.Any] = {}
162
+ kwargs = set_if_exists(kwargs, "builder", _internal.Image.BUILDER.read(config_file))
163
+ kwargs = set_if_exists(kwargs, "image_refs", _internal.Image.IMAGE_REFS.read(config_file))
164
+ return ImageConfig(**kwargs)
165
+
90
166
 
91
- return None
167
+ @rich.repr.auto
168
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
169
+ class Config(object):
170
+ """
171
+ This the parent configuration object and holds all the underlying configuration object types. An instance of
172
+ this object holds all the config necessary to
92
173
 
174
+ 1. Interactive session with Flyte backend
175
+ 2. Some parts are required for Serialization, for example Platform Config is not required
176
+ 3. Runtime of a task
177
+ """
93
178
 
94
- class ConfigFile(object):
95
- def __init__(self, location: str):
179
+ platform: PlatformConfig = field(default=PlatformConfig())
180
+ task: TaskConfig = field(default=TaskConfig())
181
+ image: ImageConfig = field(default=ImageConfig())
182
+ source: pathlib.Path | None = None
183
+
184
+ def with_params(
185
+ self,
186
+ platform: PlatformConfig | None = None,
187
+ task: TaskConfig | None = None,
188
+ image: ImageConfig | None = None,
189
+ ) -> "Config":
190
+ return Config(
191
+ platform=platform or self.platform,
192
+ task=task or self.task,
193
+ image=image or self.image,
194
+ )
195
+
196
+ @classmethod
197
+ def auto(cls, config_file: typing.Union[str, pathlib.Path, ConfigFile, None] = None) -> "Config":
96
198
  """
97
- Load the config from this location
199
+ Automatically constructs the Config Object. The order of precedence is as follows
200
+ 1. first try to find any env vars that match the config vars specified in the FLYTE_CONFIG format.
201
+ 2. If not found in environment then values ar read from the config file
202
+ 3. If not found in the file, then the default values are used.
203
+
204
+ :param config_file: file path to read the config from, if not specified default locations are searched
205
+ :return: Config
98
206
  """
99
- self._location = location
100
- self._yaml_config = self._read_yaml_config(location)
101
-
102
- @staticmethod
103
- def _read_yaml_config(location: str) -> typing.Optional[typing.Dict[str, typing.Any]]:
104
- with open(location, "r") as fh:
105
- try:
106
- yaml_contents = yaml.safe_load(fh)
107
- return yaml_contents
108
- except yaml.YAMLError as exc:
109
- logger.warning(f"Error {exc} reading yaml config file at {location}, ignoring...")
110
- return None
111
-
112
- def _get_from_yaml(self, c: YamlConfigEntry) -> typing.Any:
113
- keys = c.switch.split(".") # flytectl switches are dot delimited
114
- d = typing.cast(typing.Dict[str, typing.Any], self.yaml_config)
115
- try:
116
- for k in keys:
117
- d = d[k]
118
- return d
119
- except KeyError:
120
- return None
121
-
122
- def get(self, c: YamlConfigEntry) -> typing.Any:
123
- return self._get_from_yaml(c)
124
-
125
- @property
126
- def yaml_config(self) -> typing.Dict[str, typing.Any] | None:
127
- return self._yaml_config
128
-
129
-
130
- def resolve_config_path() -> pathlib.Path | None:
207
+ config_file = get_config_file(config_file)
208
+ if config_file is None:
209
+ logger.debug("No config file found, using default values")
210
+ return Config()
211
+ return Config(
212
+ platform=PlatformConfig.auto(config_file),
213
+ task=TaskConfig.auto(config_file),
214
+ image=ImageConfig.auto(config_file),
215
+ source=config_file.path,
216
+ )
217
+
218
+
219
+ def set_if_exists(d: dict, k: str, val: typing.Any) -> dict:
131
220
  """
132
- Config is read from the following locations in order of precedence:
133
- 1. `UCTL_CONFIG` environment variable
134
- 2. `FLYTECTL_CONFIG` environment variable
135
- 3. ~/.union/config.yaml if it exists
136
- 4. ~/.flyte/config.yaml if it exists
137
- 5. ./config.yaml if it exists
221
+ Given a dict ``d`` sets the key ``k`` with value of config ``v``, if the config value ``v`` is set
222
+ and return the updated dictionary.
138
223
  """
139
- uctl_path_from_env = getenv(UCTL_CONFIG_ENV_VAR, None)
140
- if uctl_path_from_env:
141
- return pathlib.Path(uctl_path_from_env)
142
- logger.debug("No UCTL_CONFIG environment variable found, checking FLYTECTL_CONFIG")
143
-
144
- flytectl_path_from_env = getenv(FLYTECTL_CONFIG_ENV_VAR, None)
145
- if flytectl_path_from_env:
146
- return pathlib.Path(flytectl_path_from_env)
147
- logger.debug("No FLYTECTL_CONFIG environment variable found, checking default locations")
148
-
149
- home_dir_union_config = Path(Path.home(), ".union", "config.yaml")
150
- if home_dir_union_config.exists():
151
- return home_dir_union_config
152
- logger.debug("No ~/.union/config.yaml found, checking current directory")
153
-
154
- home_dir_flytectl_config = Path(Path.home(), ".flyte", "config.yaml")
155
- if home_dir_flytectl_config.exists():
156
- return home_dir_flytectl_config
157
- logger.debug("No ~/.flyte/config.yaml found, checking current directory")
158
-
159
- current_location_config = Path("config.yaml")
160
- if current_location_config.exists():
161
- return current_location_config
162
- logger.debug("No ./config.yaml found, returning None")
163
- return None
164
-
165
-
166
- @lru_cache
167
- def get_config_file(c: typing.Union[str, ConfigFile, None]) -> ConfigFile | None:
168
- """
169
- Checks if the given argument is a file or a configFile and returns a loaded configFile else returns None
170
- """
171
- if "PYTEST_VERSION" in os.environ:
172
- # Use default local config in the pytest environment
173
- return None
174
- if isinstance(c, str):
175
- logger.debug(f"Using specified config file at {c}")
176
- return ConfigFile(c)
177
- config_path = resolve_config_path()
178
- if config_path:
179
- return ConfigFile(str(config_path))
180
- return None
181
-
182
-
183
- def read_file_if_exists(filename: typing.Optional[str], encoding=None) -> typing.Optional[str]:
184
- """
185
- Reads the contents of the file if passed a path. Otherwise, returns None.
224
+ exists = isinstance(val, bool) or bool(val is not None and val)
225
+ if exists:
226
+ d[k] = val
227
+ return d
186
228
 
187
- :param filename: The file path to load
188
- :param encoding: The encoding to use when reading the file.
189
- :return: The contents of the file as a string or None.
190
- """
191
- if not filename:
192
- return None
193
229
 
194
- file = pathlib.Path(filename)
195
- logger.debug(f"Reading file contents from [{file}] with current directory [{os.getcwd()}].")
196
- return file.read_text(encoding=encoding)
230
+ def auto(config_file: typing.Union[str, pathlib.Path, ConfigFile, None] = None) -> Config:
231
+ """
232
+ Automatically constructs the Config Object. The order of precedence is as follows
233
+ 1. If specified, read the config from the provided file path.
234
+ 2. If not specified, the config file is searched in the default locations.
235
+ a. ./config.yaml if it exists (current working directory)
236
+ b. ./.flyte/config.yaml if it exists (current working directory)
237
+ c. <git_root>/.flyte/config.yaml if it exists
238
+ d. `UCTL_CONFIG` environment variable
239
+ e. `FLYTECTL_CONFIG` environment variable
240
+ f. ~/.union/config.yaml if it exists
241
+ g. ~/.flyte/config.yaml if it exists
242
+ 3. If any value is not found in the config file, the default value is used.
243
+ 4. For any value there are environment variables that match the config variable names, those will override
244
+
245
+ :param config_file: file path to read the config from, if not specified default locations are searched
246
+ :return: Config
247
+ """
248
+ return Config.auto(config_file)
flyte/config/_internal.py CHANGED
@@ -1,4 +1,4 @@
1
- from flyte.config._config import ConfigEntry, YamlConfigEntry
1
+ from flyte.config._reader import ConfigEntry, YamlConfigEntry
2
2
 
3
3
 
4
4
  class Platform(object):
@@ -62,3 +62,12 @@ class Task(object):
62
62
  ORG = ConfigEntry(YamlConfigEntry("task.org"))
63
63
  PROJECT = ConfigEntry(YamlConfigEntry("task.project"))
64
64
  DOMAIN = ConfigEntry(YamlConfigEntry("task.domain"))
65
+
66
+
67
+ class Image(object):
68
+ """
69
+ Defines the configuration for the image builder.
70
+ """
71
+
72
+ BUILDER = ConfigEntry(YamlConfigEntry("image.builder"))
73
+ IMAGE_REFS = ConfigEntry(YamlConfigEntry("image.image_refs"))