flyte 0.1.0__py3-none-any.whl → 0.2.0b0__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.

Potentially problematic release.


This version of flyte might be problematic. Click here for more details.

Files changed (205) hide show
  1. flyte/__init__.py +62 -2
  2. flyte/_api_commons.py +3 -0
  3. flyte/_bin/__init__.py +0 -0
  4. flyte/_bin/runtime.py +126 -0
  5. flyte/_build.py +25 -0
  6. flyte/_cache/__init__.py +12 -0
  7. flyte/_cache/cache.py +146 -0
  8. flyte/_cache/defaults.py +9 -0
  9. flyte/_cache/policy_function_body.py +42 -0
  10. flyte/_cli/__init__.py +0 -0
  11. flyte/_cli/_common.py +299 -0
  12. flyte/_cli/_create.py +42 -0
  13. flyte/_cli/_delete.py +23 -0
  14. flyte/_cli/_deploy.py +140 -0
  15. flyte/_cli/_get.py +235 -0
  16. flyte/_cli/_params.py +538 -0
  17. flyte/_cli/_run.py +174 -0
  18. flyte/_cli/main.py +98 -0
  19. flyte/_code_bundle/__init__.py +8 -0
  20. flyte/_code_bundle/_ignore.py +113 -0
  21. flyte/_code_bundle/_packaging.py +187 -0
  22. flyte/_code_bundle/_utils.py +339 -0
  23. flyte/_code_bundle/bundle.py +178 -0
  24. flyte/_context.py +146 -0
  25. flyte/_datastructures.py +342 -0
  26. flyte/_deploy.py +202 -0
  27. flyte/_doc.py +29 -0
  28. flyte/_docstring.py +32 -0
  29. flyte/_environment.py +43 -0
  30. flyte/_group.py +31 -0
  31. flyte/_hash.py +23 -0
  32. flyte/_image.py +757 -0
  33. flyte/_initialize.py +643 -0
  34. flyte/_interface.py +84 -0
  35. flyte/_internal/__init__.py +3 -0
  36. flyte/_internal/controllers/__init__.py +115 -0
  37. flyte/_internal/controllers/_local_controller.py +118 -0
  38. flyte/_internal/controllers/_trace.py +40 -0
  39. flyte/_internal/controllers/pbhash.py +39 -0
  40. flyte/_internal/controllers/remote/__init__.py +40 -0
  41. flyte/_internal/controllers/remote/_action.py +141 -0
  42. flyte/_internal/controllers/remote/_client.py +43 -0
  43. flyte/_internal/controllers/remote/_controller.py +361 -0
  44. flyte/_internal/controllers/remote/_core.py +402 -0
  45. flyte/_internal/controllers/remote/_informer.py +361 -0
  46. flyte/_internal/controllers/remote/_service_protocol.py +50 -0
  47. flyte/_internal/imagebuild/__init__.py +11 -0
  48. flyte/_internal/imagebuild/docker_builder.py +416 -0
  49. flyte/_internal/imagebuild/image_builder.py +241 -0
  50. flyte/_internal/imagebuild/remote_builder.py +0 -0
  51. flyte/_internal/resolvers/__init__.py +0 -0
  52. flyte/_internal/resolvers/_task_module.py +54 -0
  53. flyte/_internal/resolvers/common.py +31 -0
  54. flyte/_internal/resolvers/default.py +28 -0
  55. flyte/_internal/runtime/__init__.py +0 -0
  56. flyte/_internal/runtime/convert.py +205 -0
  57. flyte/_internal/runtime/entrypoints.py +135 -0
  58. flyte/_internal/runtime/io.py +136 -0
  59. flyte/_internal/runtime/resources_serde.py +138 -0
  60. flyte/_internal/runtime/task_serde.py +210 -0
  61. flyte/_internal/runtime/taskrunner.py +190 -0
  62. flyte/_internal/runtime/types_serde.py +54 -0
  63. flyte/_logging.py +124 -0
  64. flyte/_protos/__init__.py +0 -0
  65. flyte/_protos/common/authorization_pb2.py +66 -0
  66. flyte/_protos/common/authorization_pb2.pyi +108 -0
  67. flyte/_protos/common/authorization_pb2_grpc.py +4 -0
  68. flyte/_protos/common/identifier_pb2.py +71 -0
  69. flyte/_protos/common/identifier_pb2.pyi +82 -0
  70. flyte/_protos/common/identifier_pb2_grpc.py +4 -0
  71. flyte/_protos/common/identity_pb2.py +48 -0
  72. flyte/_protos/common/identity_pb2.pyi +72 -0
  73. flyte/_protos/common/identity_pb2_grpc.py +4 -0
  74. flyte/_protos/common/list_pb2.py +36 -0
  75. flyte/_protos/common/list_pb2.pyi +69 -0
  76. flyte/_protos/common/list_pb2_grpc.py +4 -0
  77. flyte/_protos/common/policy_pb2.py +37 -0
  78. flyte/_protos/common/policy_pb2.pyi +27 -0
  79. flyte/_protos/common/policy_pb2_grpc.py +4 -0
  80. flyte/_protos/common/role_pb2.py +37 -0
  81. flyte/_protos/common/role_pb2.pyi +53 -0
  82. flyte/_protos/common/role_pb2_grpc.py +4 -0
  83. flyte/_protos/common/runtime_version_pb2.py +28 -0
  84. flyte/_protos/common/runtime_version_pb2.pyi +24 -0
  85. flyte/_protos/common/runtime_version_pb2_grpc.py +4 -0
  86. flyte/_protos/logs/dataplane/payload_pb2.py +96 -0
  87. flyte/_protos/logs/dataplane/payload_pb2.pyi +168 -0
  88. flyte/_protos/logs/dataplane/payload_pb2_grpc.py +4 -0
  89. flyte/_protos/secret/definition_pb2.py +49 -0
  90. flyte/_protos/secret/definition_pb2.pyi +93 -0
  91. flyte/_protos/secret/definition_pb2_grpc.py +4 -0
  92. flyte/_protos/secret/payload_pb2.py +62 -0
  93. flyte/_protos/secret/payload_pb2.pyi +94 -0
  94. flyte/_protos/secret/payload_pb2_grpc.py +4 -0
  95. flyte/_protos/secret/secret_pb2.py +38 -0
  96. flyte/_protos/secret/secret_pb2.pyi +6 -0
  97. flyte/_protos/secret/secret_pb2_grpc.py +198 -0
  98. flyte/_protos/secret/secret_pb2_grpc_grpc.py +198 -0
  99. flyte/_protos/validate/validate/validate_pb2.py +76 -0
  100. flyte/_protos/workflow/node_execution_service_pb2.py +26 -0
  101. flyte/_protos/workflow/node_execution_service_pb2.pyi +4 -0
  102. flyte/_protos/workflow/node_execution_service_pb2_grpc.py +32 -0
  103. flyte/_protos/workflow/queue_service_pb2.py +106 -0
  104. flyte/_protos/workflow/queue_service_pb2.pyi +141 -0
  105. flyte/_protos/workflow/queue_service_pb2_grpc.py +172 -0
  106. flyte/_protos/workflow/run_definition_pb2.py +128 -0
  107. flyte/_protos/workflow/run_definition_pb2.pyi +310 -0
  108. flyte/_protos/workflow/run_definition_pb2_grpc.py +4 -0
  109. flyte/_protos/workflow/run_logs_service_pb2.py +41 -0
  110. flyte/_protos/workflow/run_logs_service_pb2.pyi +28 -0
  111. flyte/_protos/workflow/run_logs_service_pb2_grpc.py +69 -0
  112. flyte/_protos/workflow/run_service_pb2.py +133 -0
  113. flyte/_protos/workflow/run_service_pb2.pyi +175 -0
  114. flyte/_protos/workflow/run_service_pb2_grpc.py +412 -0
  115. flyte/_protos/workflow/state_service_pb2.py +58 -0
  116. flyte/_protos/workflow/state_service_pb2.pyi +71 -0
  117. flyte/_protos/workflow/state_service_pb2_grpc.py +138 -0
  118. flyte/_protos/workflow/task_definition_pb2.py +72 -0
  119. flyte/_protos/workflow/task_definition_pb2.pyi +65 -0
  120. flyte/_protos/workflow/task_definition_pb2_grpc.py +4 -0
  121. flyte/_protos/workflow/task_service_pb2.py +44 -0
  122. flyte/_protos/workflow/task_service_pb2.pyi +31 -0
  123. flyte/_protos/workflow/task_service_pb2_grpc.py +104 -0
  124. flyte/_resources.py +226 -0
  125. flyte/_retry.py +32 -0
  126. flyte/_reusable_environment.py +25 -0
  127. flyte/_run.py +410 -0
  128. flyte/_secret.py +61 -0
  129. flyte/_task.py +367 -0
  130. flyte/_task_environment.py +200 -0
  131. flyte/_timeout.py +47 -0
  132. flyte/_tools.py +27 -0
  133. flyte/_trace.py +128 -0
  134. flyte/_utils/__init__.py +20 -0
  135. flyte/_utils/asyn.py +119 -0
  136. flyte/_utils/coro_management.py +25 -0
  137. flyte/_utils/file_handling.py +72 -0
  138. flyte/_utils/helpers.py +108 -0
  139. flyte/_utils/lazy_module.py +54 -0
  140. flyte/_utils/uv_script_parser.py +49 -0
  141. flyte/_version.py +21 -0
  142. flyte/config/__init__.py +168 -0
  143. flyte/config/_config.py +196 -0
  144. flyte/config/_internal.py +64 -0
  145. flyte/connectors/__init__.py +0 -0
  146. flyte/errors.py +143 -0
  147. flyte/extras/__init__.py +5 -0
  148. flyte/extras/_container.py +273 -0
  149. flyte/io/__init__.py +11 -0
  150. flyte/io/_dataframe.py +0 -0
  151. flyte/io/_dir.py +448 -0
  152. flyte/io/_file.py +468 -0
  153. flyte/io/pickle/__init__.py +0 -0
  154. flyte/io/pickle/transformer.py +117 -0
  155. flyte/io/structured_dataset/__init__.py +129 -0
  156. flyte/io/structured_dataset/basic_dfs.py +219 -0
  157. flyte/io/structured_dataset/structured_dataset.py +1061 -0
  158. flyte/remote/__init__.py +25 -0
  159. flyte/remote/_client/__init__.py +0 -0
  160. flyte/remote/_client/_protocols.py +131 -0
  161. flyte/remote/_client/auth/__init__.py +12 -0
  162. flyte/remote/_client/auth/_authenticators/__init__.py +0 -0
  163. flyte/remote/_client/auth/_authenticators/base.py +397 -0
  164. flyte/remote/_client/auth/_authenticators/client_credentials.py +73 -0
  165. flyte/remote/_client/auth/_authenticators/device_code.py +118 -0
  166. flyte/remote/_client/auth/_authenticators/external_command.py +79 -0
  167. flyte/remote/_client/auth/_authenticators/factory.py +200 -0
  168. flyte/remote/_client/auth/_authenticators/pkce.py +516 -0
  169. flyte/remote/_client/auth/_channel.py +184 -0
  170. flyte/remote/_client/auth/_client_config.py +83 -0
  171. flyte/remote/_client/auth/_default_html.py +32 -0
  172. flyte/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  173. flyte/remote/_client/auth/_grpc_utils/auth_interceptor.py +288 -0
  174. flyte/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +151 -0
  175. flyte/remote/_client/auth/_keyring.py +143 -0
  176. flyte/remote/_client/auth/_token_client.py +260 -0
  177. flyte/remote/_client/auth/errors.py +16 -0
  178. flyte/remote/_client/controlplane.py +95 -0
  179. flyte/remote/_console.py +18 -0
  180. flyte/remote/_data.py +155 -0
  181. flyte/remote/_logs.py +116 -0
  182. flyte/remote/_project.py +86 -0
  183. flyte/remote/_run.py +873 -0
  184. flyte/remote/_secret.py +132 -0
  185. flyte/remote/_task.py +227 -0
  186. flyte/report/__init__.py +3 -0
  187. flyte/report/_report.py +178 -0
  188. flyte/report/_template.html +124 -0
  189. flyte/storage/__init__.py +24 -0
  190. flyte/storage/_remote_fs.py +34 -0
  191. flyte/storage/_storage.py +251 -0
  192. flyte/storage/_utils.py +5 -0
  193. flyte/types/__init__.py +13 -0
  194. flyte/types/_interface.py +25 -0
  195. flyte/types/_renderer.py +162 -0
  196. flyte/types/_string_literals.py +120 -0
  197. flyte/types/_type_engine.py +2211 -0
  198. flyte/types/_utils.py +80 -0
  199. flyte-0.2.0b0.dist-info/METADATA +179 -0
  200. flyte-0.2.0b0.dist-info/RECORD +204 -0
  201. {flyte-0.1.0.dist-info → flyte-0.2.0b0.dist-info}/WHEEL +2 -1
  202. flyte-0.2.0b0.dist-info/entry_points.txt +3 -0
  203. flyte-0.2.0b0.dist-info/top_level.txt +1 -0
  204. flyte-0.1.0.dist-info/METADATA +0 -6
  205. flyte-0.1.0.dist-info/RECORD +0 -5
@@ -0,0 +1,168 @@
1
+ import os
2
+ import typing
3
+ from dataclasses import dataclass, field
4
+ from typing import TYPE_CHECKING
5
+
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))
@@ -0,0 +1,196 @@
1
+ import os
2
+ import pathlib
3
+ import typing
4
+ from dataclasses import dataclass
5
+ from functools import lru_cache
6
+ from os import getenv
7
+ from pathlib import Path
8
+
9
+ import yaml
10
+
11
+ from flyte._logging import logger
12
+
13
+ # This is the default config file name for flyte
14
+ FLYTECTL_CONFIG_ENV_VAR = "FLYTECTL_CONFIG"
15
+ UCTL_CONFIG_ENV_VAR = "UCTL_CONFIG"
16
+
17
+
18
+ @dataclass
19
+ class YamlConfigEntry(object):
20
+ """
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
+ """
27
+
28
+ switch: str
29
+ config_value_type: typing.Type = str
30
+
31
+ def get_env_name(self) -> str:
32
+ var_name = self.switch.upper().replace(".", "_")
33
+ return f"FLYTE_{var_name}"
34
+
35
+ def read_from_env(self, transform: typing.Optional[typing.Callable] = None) -> typing.Optional[typing.Any]:
36
+ """
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.
39
+ :return:
40
+ """
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):
64
+ """
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
68
+ """
69
+
70
+ yaml_entry: YamlConfigEntry
71
+ transform: typing.Optional[typing.Callable[[str], typing.Any]] = None
72
+
73
+ def read(self, cfg: typing.Optional["ConfigFile"] = None) -> typing.Optional[typing.Any]:
74
+ """
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:
83
+ :return:
84
+ """
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)
90
+
91
+ return None
92
+
93
+
94
+ class ConfigFile(object):
95
+ def __init__(self, location: str):
96
+ """
97
+ Load the config from this location
98
+ """
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:
131
+ """
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
138
+ """
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.
186
+
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
+
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)
@@ -0,0 +1,64 @@
1
+ from flyte.config._config import ConfigEntry, YamlConfigEntry
2
+
3
+
4
+ class Platform(object):
5
+ URL = ConfigEntry(YamlConfigEntry("admin.endpoint"))
6
+ INSECURE = ConfigEntry(YamlConfigEntry("admin.insecure", bool))
7
+ INSECURE_SKIP_VERIFY = ConfigEntry(YamlConfigEntry("admin.insecureSkipVerify", bool))
8
+ CONSOLE_ENDPOINT = ConfigEntry(YamlConfigEntry("console.endpoint"))
9
+ CA_CERT_FILE_PATH = ConfigEntry(YamlConfigEntry("admin.caCertFilePath"))
10
+ HTTP_PROXY_URL = ConfigEntry(YamlConfigEntry("admin.httpProxyURL"))
11
+
12
+
13
+ class Credentials(object):
14
+ SECTION = "credentials"
15
+ COMMAND = ConfigEntry(YamlConfigEntry("admin.command", list))
16
+ """
17
+ This command is executed to return a token using an external process.
18
+ """
19
+
20
+ PROXY_COMMAND = ConfigEntry(YamlConfigEntry("admin.proxyCommand", list))
21
+ """
22
+ This command is executed to return a token for authorization with a proxy
23
+ in front of Flyte using an external process.
24
+ """
25
+
26
+ CLIENT_ID = ConfigEntry(YamlConfigEntry("admin.clientId"))
27
+ """
28
+ This is the public identifier for the app which handles authorization for a Flyte deployment.
29
+ More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
30
+ """
31
+
32
+ CLIENT_CREDENTIALS_SECRET_LOCATION = ConfigEntry(YamlConfigEntry("admin.clientSecretLocation"))
33
+ """
34
+ Used for basic auth, which is automatically called during pyflyte. This will allow the Flyte engine to read the
35
+ password from a mounted file.
36
+ """
37
+
38
+ CLIENT_CREDENTIALS_SECRET_ENV_VAR = ConfigEntry(YamlConfigEntry("admin.clientSecretEnvVar"))
39
+ """
40
+ Used for basic auth, which is automatically called during pyflyte. This will allow the Flyte engine to read the
41
+ password from a mounted environment variable.
42
+ """
43
+
44
+ SCOPES = ConfigEntry(YamlConfigEntry("admin.scopes", list))
45
+ """
46
+ This setting can be used to manually pass in scopes into authenticator flows - eg.) for Auth0 compatibility
47
+ """
48
+
49
+ AUTH_MODE = ConfigEntry(YamlConfigEntry("admin.authType"))
50
+ """
51
+ The auth mode defines the behavior used to request and refresh credentials. The currently supported modes include:
52
+ - 'standard' or 'Pkce': This uses the pkce-enhanced authorization code flow by opening a browser window to initiate
53
+ credentials access.
54
+ - "DeviceFlow": This uses the Device Authorization Flow
55
+ - 'basic', 'client_credentials' or 'clientSecret': This uses symmetric key auth in which the end user enters a
56
+ client id and a client secret and public key encryption is used to facilitate authentication.
57
+ - None: No auth will be attempted.
58
+ """
59
+
60
+
61
+ class Task(object):
62
+ ORG = ConfigEntry(YamlConfigEntry("task.org"))
63
+ PROJECT = ConfigEntry(YamlConfigEntry("task.project"))
64
+ DOMAIN = ConfigEntry(YamlConfigEntry("task.domain"))
File without changes
flyte/errors.py ADDED
@@ -0,0 +1,143 @@
1
+ """
2
+ Exceptions raised by Union.
3
+
4
+ These errors are raised when the underlying task execution fails, either because of a user error, system error or an
5
+ unknown error.
6
+ """
7
+
8
+ from typing import Literal
9
+
10
+ ErrorKind = Literal["system", "unknown", "user"]
11
+
12
+
13
+ class BaseRuntimeError(RuntimeError):
14
+ """
15
+ Base class for all Union runtime errors. These errors are raised when the underlying task execution fails, either
16
+ because of a user error, system error or an unknown error.
17
+ """
18
+
19
+ def __init__(self, code: str, kind: ErrorKind, root_cause_message: str, worker: str | None = None):
20
+ super().__init__(root_cause_message)
21
+ self.code = code
22
+ self.kind = kind
23
+ self.worker = worker
24
+
25
+
26
+ class InitializationError(BaseRuntimeError):
27
+ """
28
+ This error is raised when the Union system is tried to access without being initialized.
29
+ """
30
+
31
+
32
+ class RuntimeSystemError(BaseRuntimeError):
33
+ """
34
+ This error is raised when the underlying task execution fails because of a system error. This could be a bug in the
35
+ Union system or a bug in the user's code.
36
+ """
37
+
38
+ def __init__(self, code: str, message: str, worker: str | None = None):
39
+ super().__init__(code, "system", message, worker)
40
+
41
+
42
+ class UnionRpcError(RuntimeSystemError):
43
+ """
44
+ This error is raised when communication with the Union server fails.
45
+ """
46
+
47
+
48
+ class RuntimeUserError(BaseRuntimeError):
49
+ """
50
+ This error is raised when the underlying task execution fails because of an error in the user's code.
51
+ """
52
+
53
+ def __init__(self, code: str, message: str, worker: str | None = None):
54
+ super().__init__(code, "user", message, worker)
55
+
56
+
57
+ class RuntimeUnknownError(BaseRuntimeError):
58
+ """
59
+ This error is raised when the underlying task execution fails because of an unknown error.
60
+ """
61
+
62
+ def __init__(self, code: str, message: str, worker: str | None = None):
63
+ super().__init__(code, "unknown", message, worker)
64
+
65
+
66
+ class OOMError(RuntimeUserError):
67
+ """
68
+ This error is raised when the underlying task execution fails because of an out-of-memory error.
69
+ """
70
+
71
+
72
+ class TaskInterruptedError(RuntimeUserError):
73
+ """
74
+ This error is raised when the underlying task execution is interrupted.
75
+ """
76
+
77
+
78
+ class PrimaryContainerNotFoundError(RuntimeUserError):
79
+ """
80
+ This error is raised when the primary container is not found.
81
+ """
82
+
83
+
84
+ class TaskTimeoutError(RuntimeUserError):
85
+ """
86
+ This error is raised when the underlying task execution runs for longer than the specified timeout.
87
+ """
88
+
89
+
90
+ class RetriesExhaustedError(RuntimeUserError):
91
+ """
92
+ This error is raised when the underlying task execution fails after all retries have been exhausted.
93
+ """
94
+
95
+
96
+ class InvalidImageNameError(RuntimeUserError):
97
+ """
98
+ This error is raised when the image name is invalid.
99
+ """
100
+
101
+
102
+ class ImagePullBackOffError(RuntimeUserError):
103
+ """
104
+ This error is raised when the image cannot be pulled.
105
+ """
106
+
107
+
108
+ class CustomError(RuntimeUserError):
109
+ """
110
+ This error is raised when the user raises a custom error.
111
+ """
112
+
113
+ def __init__(self, code: str, message: str):
114
+ super().__init__(code, message, "user")
115
+
116
+ @classmethod
117
+ def from_exception(cls, e: Exception):
118
+ """
119
+ Create a CustomError from an exception. The exception's class name is used as the error code and the exception
120
+ message is used as the error message.
121
+ """
122
+ return cls(e.__class__.__name__, str(e))
123
+
124
+
125
+ class NotInTaskContextError(RuntimeUserError):
126
+ """
127
+ This error is raised when the user tries to access the task context outside of a task.
128
+ """
129
+
130
+
131
+ class ActionNotFoundError(RuntimeError):
132
+ """
133
+ This error is raised when the user tries to access an action that does not exist.
134
+ """
135
+
136
+
137
+ class ReferenceTaskError(RuntimeUserError):
138
+ """
139
+ This error is raised when the user tries to access a task that does not exist.
140
+ """
141
+
142
+ def __init__(self, message: str):
143
+ super().__init__("ReferenceTaskUsageError", message, "user")
@@ -0,0 +1,5 @@
1
+ from ._container import ContainerTask
2
+
3
+ __all__ = [
4
+ "ContainerTask",
5
+ ]