flyte 0.1.0__py3-none-any.whl → 0.2.0a0__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.
- flyte/__init__.py +78 -2
- flyte/_bin/__init__.py +0 -0
- flyte/_bin/runtime.py +152 -0
- flyte/_build.py +26 -0
- flyte/_cache/__init__.py +12 -0
- flyte/_cache/cache.py +145 -0
- flyte/_cache/defaults.py +9 -0
- flyte/_cache/policy_function_body.py +42 -0
- flyte/_code_bundle/__init__.py +8 -0
- flyte/_code_bundle/_ignore.py +113 -0
- flyte/_code_bundle/_packaging.py +187 -0
- flyte/_code_bundle/_utils.py +323 -0
- flyte/_code_bundle/bundle.py +209 -0
- flyte/_context.py +152 -0
- flyte/_deploy.py +243 -0
- flyte/_doc.py +29 -0
- flyte/_docstring.py +32 -0
- flyte/_environment.py +84 -0
- flyte/_excepthook.py +37 -0
- flyte/_group.py +32 -0
- flyte/_hash.py +23 -0
- flyte/_image.py +762 -0
- flyte/_initialize.py +492 -0
- flyte/_interface.py +84 -0
- flyte/_internal/__init__.py +3 -0
- flyte/_internal/controllers/__init__.py +128 -0
- flyte/_internal/controllers/_local_controller.py +193 -0
- flyte/_internal/controllers/_trace.py +41 -0
- flyte/_internal/controllers/remote/__init__.py +60 -0
- flyte/_internal/controllers/remote/_action.py +146 -0
- flyte/_internal/controllers/remote/_client.py +47 -0
- flyte/_internal/controllers/remote/_controller.py +494 -0
- flyte/_internal/controllers/remote/_core.py +410 -0
- flyte/_internal/controllers/remote/_informer.py +361 -0
- flyte/_internal/controllers/remote/_service_protocol.py +50 -0
- flyte/_internal/imagebuild/__init__.py +11 -0
- flyte/_internal/imagebuild/docker_builder.py +427 -0
- flyte/_internal/imagebuild/image_builder.py +246 -0
- flyte/_internal/imagebuild/remote_builder.py +0 -0
- flyte/_internal/resolvers/__init__.py +0 -0
- flyte/_internal/resolvers/_task_module.py +54 -0
- flyte/_internal/resolvers/common.py +31 -0
- flyte/_internal/resolvers/default.py +28 -0
- flyte/_internal/runtime/__init__.py +0 -0
- flyte/_internal/runtime/convert.py +342 -0
- flyte/_internal/runtime/entrypoints.py +135 -0
- flyte/_internal/runtime/io.py +136 -0
- flyte/_internal/runtime/resources_serde.py +138 -0
- flyte/_internal/runtime/task_serde.py +330 -0
- flyte/_internal/runtime/taskrunner.py +191 -0
- flyte/_internal/runtime/types_serde.py +54 -0
- flyte/_logging.py +135 -0
- flyte/_map.py +215 -0
- flyte/_pod.py +19 -0
- flyte/_protos/__init__.py +0 -0
- flyte/_protos/common/authorization_pb2.py +66 -0
- flyte/_protos/common/authorization_pb2.pyi +108 -0
- flyte/_protos/common/authorization_pb2_grpc.py +4 -0
- flyte/_protos/common/identifier_pb2.py +71 -0
- flyte/_protos/common/identifier_pb2.pyi +82 -0
- flyte/_protos/common/identifier_pb2_grpc.py +4 -0
- flyte/_protos/common/identity_pb2.py +48 -0
- flyte/_protos/common/identity_pb2.pyi +72 -0
- flyte/_protos/common/identity_pb2_grpc.py +4 -0
- flyte/_protos/common/list_pb2.py +36 -0
- flyte/_protos/common/list_pb2.pyi +71 -0
- flyte/_protos/common/list_pb2_grpc.py +4 -0
- flyte/_protos/common/policy_pb2.py +37 -0
- flyte/_protos/common/policy_pb2.pyi +27 -0
- flyte/_protos/common/policy_pb2_grpc.py +4 -0
- flyte/_protos/common/role_pb2.py +37 -0
- flyte/_protos/common/role_pb2.pyi +53 -0
- flyte/_protos/common/role_pb2_grpc.py +4 -0
- flyte/_protos/common/runtime_version_pb2.py +28 -0
- flyte/_protos/common/runtime_version_pb2.pyi +24 -0
- flyte/_protos/common/runtime_version_pb2_grpc.py +4 -0
- flyte/_protos/logs/dataplane/payload_pb2.py +100 -0
- flyte/_protos/logs/dataplane/payload_pb2.pyi +177 -0
- flyte/_protos/logs/dataplane/payload_pb2_grpc.py +4 -0
- flyte/_protos/secret/definition_pb2.py +49 -0
- flyte/_protos/secret/definition_pb2.pyi +93 -0
- flyte/_protos/secret/definition_pb2_grpc.py +4 -0
- flyte/_protos/secret/payload_pb2.py +62 -0
- flyte/_protos/secret/payload_pb2.pyi +94 -0
- flyte/_protos/secret/payload_pb2_grpc.py +4 -0
- flyte/_protos/secret/secret_pb2.py +38 -0
- flyte/_protos/secret/secret_pb2.pyi +6 -0
- flyte/_protos/secret/secret_pb2_grpc.py +198 -0
- flyte/_protos/secret/secret_pb2_grpc_grpc.py +198 -0
- flyte/_protos/validate/validate/validate_pb2.py +76 -0
- flyte/_protos/workflow/common_pb2.py +27 -0
- flyte/_protos/workflow/common_pb2.pyi +14 -0
- flyte/_protos/workflow/common_pb2_grpc.py +4 -0
- flyte/_protos/workflow/environment_pb2.py +29 -0
- flyte/_protos/workflow/environment_pb2.pyi +12 -0
- flyte/_protos/workflow/environment_pb2_grpc.py +4 -0
- flyte/_protos/workflow/node_execution_service_pb2.py +26 -0
- flyte/_protos/workflow/node_execution_service_pb2.pyi +4 -0
- flyte/_protos/workflow/node_execution_service_pb2_grpc.py +32 -0
- flyte/_protos/workflow/queue_service_pb2.py +105 -0
- flyte/_protos/workflow/queue_service_pb2.pyi +146 -0
- flyte/_protos/workflow/queue_service_pb2_grpc.py +172 -0
- flyte/_protos/workflow/run_definition_pb2.py +128 -0
- flyte/_protos/workflow/run_definition_pb2.pyi +314 -0
- flyte/_protos/workflow/run_definition_pb2_grpc.py +4 -0
- flyte/_protos/workflow/run_logs_service_pb2.py +41 -0
- flyte/_protos/workflow/run_logs_service_pb2.pyi +28 -0
- flyte/_protos/workflow/run_logs_service_pb2_grpc.py +69 -0
- flyte/_protos/workflow/run_service_pb2.py +129 -0
- flyte/_protos/workflow/run_service_pb2.pyi +171 -0
- flyte/_protos/workflow/run_service_pb2_grpc.py +412 -0
- flyte/_protos/workflow/state_service_pb2.py +66 -0
- flyte/_protos/workflow/state_service_pb2.pyi +75 -0
- flyte/_protos/workflow/state_service_pb2_grpc.py +138 -0
- flyte/_protos/workflow/task_definition_pb2.py +79 -0
- flyte/_protos/workflow/task_definition_pb2.pyi +81 -0
- flyte/_protos/workflow/task_definition_pb2_grpc.py +4 -0
- flyte/_protos/workflow/task_service_pb2.py +60 -0
- flyte/_protos/workflow/task_service_pb2.pyi +59 -0
- flyte/_protos/workflow/task_service_pb2_grpc.py +138 -0
- flyte/_resources.py +226 -0
- flyte/_retry.py +32 -0
- flyte/_reusable_environment.py +25 -0
- flyte/_run.py +482 -0
- flyte/_secret.py +61 -0
- flyte/_task.py +449 -0
- flyte/_task_environment.py +183 -0
- flyte/_timeout.py +47 -0
- flyte/_tools.py +27 -0
- flyte/_trace.py +120 -0
- flyte/_utils/__init__.py +26 -0
- flyte/_utils/asyn.py +119 -0
- flyte/_utils/async_cache.py +139 -0
- flyte/_utils/coro_management.py +23 -0
- flyte/_utils/file_handling.py +72 -0
- flyte/_utils/helpers.py +134 -0
- flyte/_utils/lazy_module.py +54 -0
- flyte/_utils/org_discovery.py +57 -0
- flyte/_utils/uv_script_parser.py +49 -0
- flyte/_version.py +21 -0
- flyte/cli/__init__.py +3 -0
- flyte/cli/_abort.py +28 -0
- flyte/cli/_common.py +337 -0
- flyte/cli/_create.py +145 -0
- flyte/cli/_delete.py +23 -0
- flyte/cli/_deploy.py +152 -0
- flyte/cli/_gen.py +163 -0
- flyte/cli/_get.py +310 -0
- flyte/cli/_params.py +538 -0
- flyte/cli/_run.py +231 -0
- flyte/cli/main.py +166 -0
- flyte/config/__init__.py +3 -0
- flyte/config/_config.py +216 -0
- flyte/config/_internal.py +64 -0
- flyte/config/_reader.py +207 -0
- flyte/connectors/__init__.py +0 -0
- flyte/errors.py +172 -0
- flyte/extras/__init__.py +5 -0
- flyte/extras/_container.py +263 -0
- flyte/io/__init__.py +27 -0
- flyte/io/_dir.py +448 -0
- flyte/io/_file.py +467 -0
- flyte/io/_structured_dataset/__init__.py +129 -0
- flyte/io/_structured_dataset/basic_dfs.py +219 -0
- flyte/io/_structured_dataset/structured_dataset.py +1061 -0
- flyte/models.py +391 -0
- flyte/remote/__init__.py +26 -0
- flyte/remote/_client/__init__.py +0 -0
- flyte/remote/_client/_protocols.py +133 -0
- flyte/remote/_client/auth/__init__.py +12 -0
- flyte/remote/_client/auth/_auth_utils.py +14 -0
- flyte/remote/_client/auth/_authenticators/__init__.py +0 -0
- flyte/remote/_client/auth/_authenticators/base.py +397 -0
- flyte/remote/_client/auth/_authenticators/client_credentials.py +73 -0
- flyte/remote/_client/auth/_authenticators/device_code.py +118 -0
- flyte/remote/_client/auth/_authenticators/external_command.py +79 -0
- flyte/remote/_client/auth/_authenticators/factory.py +200 -0
- flyte/remote/_client/auth/_authenticators/pkce.py +516 -0
- flyte/remote/_client/auth/_channel.py +215 -0
- flyte/remote/_client/auth/_client_config.py +83 -0
- flyte/remote/_client/auth/_default_html.py +32 -0
- flyte/remote/_client/auth/_grpc_utils/__init__.py +0 -0
- flyte/remote/_client/auth/_grpc_utils/auth_interceptor.py +288 -0
- flyte/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +151 -0
- flyte/remote/_client/auth/_keyring.py +143 -0
- flyte/remote/_client/auth/_token_client.py +260 -0
- flyte/remote/_client/auth/errors.py +16 -0
- flyte/remote/_client/controlplane.py +95 -0
- flyte/remote/_console.py +18 -0
- flyte/remote/_data.py +159 -0
- flyte/remote/_logs.py +176 -0
- flyte/remote/_project.py +85 -0
- flyte/remote/_run.py +970 -0
- flyte/remote/_secret.py +132 -0
- flyte/remote/_task.py +391 -0
- flyte/report/__init__.py +3 -0
- flyte/report/_report.py +178 -0
- flyte/report/_template.html +124 -0
- flyte/storage/__init__.py +29 -0
- flyte/storage/_config.py +233 -0
- flyte/storage/_remote_fs.py +34 -0
- flyte/storage/_storage.py +271 -0
- flyte/storage/_utils.py +5 -0
- flyte/syncify/__init__.py +56 -0
- flyte/syncify/_api.py +371 -0
- flyte/types/__init__.py +36 -0
- flyte/types/_interface.py +40 -0
- flyte/types/_pickle.py +118 -0
- flyte/types/_renderer.py +162 -0
- flyte/types/_string_literals.py +120 -0
- flyte/types/_type_engine.py +2287 -0
- flyte/types/_utils.py +80 -0
- flyte-0.2.0a0.dist-info/METADATA +249 -0
- flyte-0.2.0a0.dist-info/RECORD +218 -0
- {flyte-0.1.0.dist-info → flyte-0.2.0a0.dist-info}/WHEEL +2 -1
- flyte-0.2.0a0.dist-info/entry_points.txt +3 -0
- flyte-0.2.0a0.dist-info/top_level.txt +1 -0
- flyte-0.1.0.dist-info/METADATA +0 -6
- flyte-0.1.0.dist-info/RECORD +0 -5
flyte/cli/_run.py
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import inspect
|
|
5
|
+
from dataclasses import dataclass, field, fields
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from types import ModuleType
|
|
8
|
+
from typing import Any, Dict, List, cast
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
from click import Context, Parameter
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
from typing_extensions import get_args
|
|
14
|
+
|
|
15
|
+
from .._code_bundle._utils import CopyFiles
|
|
16
|
+
from .._task import TaskTemplate
|
|
17
|
+
from ..remote import Run
|
|
18
|
+
from . import _common as common
|
|
19
|
+
from ._common import CLIConfig
|
|
20
|
+
from ._params import to_click_option
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class RunArguments:
|
|
25
|
+
project: str = field(
|
|
26
|
+
default=cast(str, common.PROJECT_OPTION.default), metadata={"click.option": common.PROJECT_OPTION}
|
|
27
|
+
)
|
|
28
|
+
domain: str = field(
|
|
29
|
+
default=cast(str, common.DOMAIN_OPTION.default), metadata={"click.option": common.DOMAIN_OPTION}
|
|
30
|
+
)
|
|
31
|
+
local: bool = field(
|
|
32
|
+
default=False,
|
|
33
|
+
metadata={
|
|
34
|
+
"click.option": click.Option(
|
|
35
|
+
["--local"],
|
|
36
|
+
is_flag=True,
|
|
37
|
+
help="Run the task locally",
|
|
38
|
+
)
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
copy_style: CopyFiles = field(
|
|
42
|
+
default="loaded_modules",
|
|
43
|
+
metadata={
|
|
44
|
+
"click.option": click.Option(
|
|
45
|
+
["--copy-style"],
|
|
46
|
+
type=click.Choice(get_args(CopyFiles)),
|
|
47
|
+
default="loaded_modules",
|
|
48
|
+
help="Copy style to use when running the task",
|
|
49
|
+
)
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
name: str | None = field(
|
|
53
|
+
default=None,
|
|
54
|
+
metadata={
|
|
55
|
+
"click.option": click.Option(
|
|
56
|
+
["--name"],
|
|
57
|
+
type=str,
|
|
58
|
+
help="Name of the run. If not provided, a random name will be generated.",
|
|
59
|
+
)
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
follow: bool = field(
|
|
63
|
+
default=True,
|
|
64
|
+
metadata={
|
|
65
|
+
"click.option": click.Option(
|
|
66
|
+
["--follow", "-f"],
|
|
67
|
+
is_flag=True,
|
|
68
|
+
default=False,
|
|
69
|
+
help="Wait and watch logs for the parent action. If not provided, the CLI will exit after "
|
|
70
|
+
"successfully launching a remote execution with a link to the UI.",
|
|
71
|
+
)
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def from_dict(cls, d: Dict[str, Any]) -> RunArguments:
|
|
77
|
+
return cls(**d)
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def options(cls) -> List[click.Option]:
|
|
81
|
+
"""
|
|
82
|
+
Return the set of base parameters added to run subcommand.
|
|
83
|
+
"""
|
|
84
|
+
return [common.get_option_from_metadata(f.metadata) for f in fields(cls) if f.metadata]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class RunTaskCommand(click.Command):
|
|
88
|
+
def __init__(self, obj_name: str, obj: Any, run_args: RunArguments, *args, **kwargs):
|
|
89
|
+
self.obj_name = obj_name
|
|
90
|
+
self.obj = cast(TaskTemplate, obj)
|
|
91
|
+
self.run_args = run_args
|
|
92
|
+
kwargs.pop("name", None)
|
|
93
|
+
super().__init__(obj_name, *args, **kwargs)
|
|
94
|
+
|
|
95
|
+
def invoke(self, ctx: Context):
|
|
96
|
+
obj: CLIConfig = ctx.obj
|
|
97
|
+
if obj is None:
|
|
98
|
+
import flyte.config
|
|
99
|
+
|
|
100
|
+
obj = CLIConfig(flyte.config.auto(), ctx)
|
|
101
|
+
|
|
102
|
+
obj.init(self.run_args.project, self.run_args.domain)
|
|
103
|
+
|
|
104
|
+
async def _run():
|
|
105
|
+
import flyte
|
|
106
|
+
|
|
107
|
+
r = flyte.with_runcontext(
|
|
108
|
+
copy_style=self.run_args.copy_style,
|
|
109
|
+
mode="local" if self.run_args.local else "remote",
|
|
110
|
+
name=self.run_args.name,
|
|
111
|
+
).run(self.obj, **ctx.params)
|
|
112
|
+
if isinstance(r, Run) and r.action is not None:
|
|
113
|
+
console = Console()
|
|
114
|
+
console.print(
|
|
115
|
+
common.get_panel(
|
|
116
|
+
"Run",
|
|
117
|
+
f"[green bold]Created Run: {r.name} [/green bold] "
|
|
118
|
+
f"(Project: {r.action.action_id.run.project}, Domain: {r.action.action_id.run.domain})\n"
|
|
119
|
+
f"➡️ [blue bold]{r.url}[/blue bold]",
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
if self.run_args.follow:
|
|
123
|
+
console.print(
|
|
124
|
+
"[dim]Log streaming enabled, will wait for task to start running "
|
|
125
|
+
"and log stream to be available[/dim]"
|
|
126
|
+
)
|
|
127
|
+
await r.show_logs(max_lines=30, show_ts=True, raw=False)
|
|
128
|
+
|
|
129
|
+
asyncio.run(_run())
|
|
130
|
+
|
|
131
|
+
def get_params(self, ctx: Context) -> List[Parameter]:
|
|
132
|
+
# Note this function may be called multiple times by click.
|
|
133
|
+
task = self.obj
|
|
134
|
+
from .._internal.runtime.types_serde import transform_native_to_typed_interface
|
|
135
|
+
|
|
136
|
+
interface = transform_native_to_typed_interface(task.native_interface)
|
|
137
|
+
if interface is None:
|
|
138
|
+
return super().get_params(ctx)
|
|
139
|
+
inputs_interface = task.native_interface.inputs
|
|
140
|
+
|
|
141
|
+
params: List[Parameter] = []
|
|
142
|
+
for name, var in interface.inputs.variables.items():
|
|
143
|
+
default_val = None
|
|
144
|
+
if inputs_interface[name][1] is not inspect._empty:
|
|
145
|
+
default_val = inputs_interface[name][1]
|
|
146
|
+
params.append(to_click_option(name, var, inputs_interface[name][0], default_val))
|
|
147
|
+
|
|
148
|
+
self.params = params
|
|
149
|
+
return super().get_params(ctx)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class TaskPerFileGroup(common.ObjectsPerFileGroup):
|
|
153
|
+
"""
|
|
154
|
+
Group that creates a command for each task in the current directory that is not __init__.py.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
def __init__(self, filename: Path, run_args: RunArguments, *args, **kwargs):
|
|
158
|
+
args = (filename, *args)
|
|
159
|
+
super().__init__(*args, **kwargs)
|
|
160
|
+
self.run_args = run_args
|
|
161
|
+
|
|
162
|
+
def _filter_objects(self, module: ModuleType) -> Dict[str, Any]:
|
|
163
|
+
return {k: v for k, v in module.__dict__.items() if isinstance(v, TaskTemplate)}
|
|
164
|
+
|
|
165
|
+
def _get_command_for_obj(self, ctx: click.Context, obj_name: str, obj: Any) -> click.Command:
|
|
166
|
+
obj = cast(TaskTemplate, obj)
|
|
167
|
+
return RunTaskCommand(
|
|
168
|
+
obj_name=obj_name,
|
|
169
|
+
obj=obj,
|
|
170
|
+
help=obj.docs.__help__str__() if obj.docs else None,
|
|
171
|
+
run_args=self.run_args,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class TaskFiles(common.FileGroup):
|
|
176
|
+
"""
|
|
177
|
+
Group that creates a command for each file in the current directory that is not __init__.py.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
common_options_enabled = False
|
|
181
|
+
|
|
182
|
+
def __init__(
|
|
183
|
+
self,
|
|
184
|
+
*args,
|
|
185
|
+
directory: Path | None = None,
|
|
186
|
+
**kwargs,
|
|
187
|
+
):
|
|
188
|
+
if "params" not in kwargs:
|
|
189
|
+
kwargs["params"] = []
|
|
190
|
+
kwargs["params"].extend(RunArguments.options())
|
|
191
|
+
super().__init__(*args, directory=directory, **kwargs)
|
|
192
|
+
|
|
193
|
+
def get_command(self, ctx, filename):
|
|
194
|
+
run_args = RunArguments.from_dict(ctx.params)
|
|
195
|
+
fp = Path(filename)
|
|
196
|
+
if not fp.exists():
|
|
197
|
+
raise click.BadParameter(f"File {filename} does not exist")
|
|
198
|
+
if fp.is_dir():
|
|
199
|
+
return TaskFiles(directory=fp)
|
|
200
|
+
return TaskPerFileGroup(
|
|
201
|
+
filename=Path(filename),
|
|
202
|
+
run_args=run_args,
|
|
203
|
+
name=filename,
|
|
204
|
+
help=f"Run, functions decorated with `env.task` in {filename}",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
run = TaskFiles(
|
|
209
|
+
name="run",
|
|
210
|
+
help="""
|
|
211
|
+
Run a task from a python file.
|
|
212
|
+
|
|
213
|
+
Example usage:
|
|
214
|
+
```bash
|
|
215
|
+
flyte run --name examples/basics/hello.py my_task --arg1 value1 --arg2 value2
|
|
216
|
+
```
|
|
217
|
+
Note: all arguments for the run command are provided right after the `run` command and before the file name.
|
|
218
|
+
|
|
219
|
+
You can also specify the project and domain using the `--project` and `--domain` options, respectively. These
|
|
220
|
+
options can be set in the config file or passed as command line arguments.
|
|
221
|
+
|
|
222
|
+
Note: The arguments for the task are provided after the task name and can be retrieved using `--help`
|
|
223
|
+
Example:
|
|
224
|
+
```bash
|
|
225
|
+
flyte run --name examples/basics/hello.py my_task --help
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
To run a task locally, use the `--local` flag. This will run the task in the local environment instead of the remote
|
|
229
|
+
Flyte environment.
|
|
230
|
+
""",
|
|
231
|
+
)
|
flyte/cli/main.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import rich_click as click
|
|
2
|
+
|
|
3
|
+
from flyte._logging import initialize_logger, logger
|
|
4
|
+
|
|
5
|
+
from ._abort import abort
|
|
6
|
+
from ._common import CLIConfig
|
|
7
|
+
from ._create import create
|
|
8
|
+
from ._delete import delete
|
|
9
|
+
from ._deploy import deploy
|
|
10
|
+
from ._gen import gen
|
|
11
|
+
from ._get import get
|
|
12
|
+
from ._run import run
|
|
13
|
+
|
|
14
|
+
help_config = click.RichHelpConfiguration(
|
|
15
|
+
use_markdown=True,
|
|
16
|
+
use_markdown_emoji=True,
|
|
17
|
+
command_groups={
|
|
18
|
+
"flyte": [
|
|
19
|
+
{
|
|
20
|
+
"name": "Run and stop tasks",
|
|
21
|
+
"commands": ["run", "abort"],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "Management",
|
|
25
|
+
"commands": ["create", "deploy", "get", "delete"],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "Documentation generation",
|
|
29
|
+
"commands": ["gen"],
|
|
30
|
+
},
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _verbosity_to_loglevel(verbosity: int) -> int | None:
|
|
37
|
+
"""
|
|
38
|
+
Converts a verbosity level from the CLI to a logging level.
|
|
39
|
+
|
|
40
|
+
:param verbosity: verbosity level from the CLI
|
|
41
|
+
:return: logging level
|
|
42
|
+
"""
|
|
43
|
+
import logging
|
|
44
|
+
|
|
45
|
+
match verbosity:
|
|
46
|
+
case 0:
|
|
47
|
+
return None
|
|
48
|
+
case 1:
|
|
49
|
+
return logging.WARNING
|
|
50
|
+
case 2:
|
|
51
|
+
return logging.INFO
|
|
52
|
+
case _:
|
|
53
|
+
return logging.DEBUG
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@click.group(cls=click.RichGroup)
|
|
57
|
+
@click.option(
|
|
58
|
+
"--endpoint",
|
|
59
|
+
type=str,
|
|
60
|
+
required=False,
|
|
61
|
+
help="The endpoint to connect to. This will override any configuration file and simply use `pkce` to connect.",
|
|
62
|
+
)
|
|
63
|
+
@click.option(
|
|
64
|
+
"--insecure",
|
|
65
|
+
is_flag=True,
|
|
66
|
+
required=False,
|
|
67
|
+
help="Use an insecure connection to the endpoint. If not specified, the CLI will use TLS.",
|
|
68
|
+
type=bool,
|
|
69
|
+
default=None,
|
|
70
|
+
show_default=True,
|
|
71
|
+
)
|
|
72
|
+
@click.option(
|
|
73
|
+
"-v",
|
|
74
|
+
"--verbose",
|
|
75
|
+
required=False,
|
|
76
|
+
help="Show verbose messages and exception traces. Repeating multiple times increases the verbosity (e.g., -vvv).",
|
|
77
|
+
count=True,
|
|
78
|
+
default=0,
|
|
79
|
+
type=int,
|
|
80
|
+
)
|
|
81
|
+
@click.option(
|
|
82
|
+
"--org",
|
|
83
|
+
type=str,
|
|
84
|
+
required=False,
|
|
85
|
+
help="The organization to which the command applies.",
|
|
86
|
+
)
|
|
87
|
+
@click.option(
|
|
88
|
+
"-c",
|
|
89
|
+
"--config",
|
|
90
|
+
"config_file",
|
|
91
|
+
required=False,
|
|
92
|
+
type=click.Path(exists=True),
|
|
93
|
+
help="Path to the configuration file to use. If not specified, the default configuration file is used.",
|
|
94
|
+
)
|
|
95
|
+
@click.rich_config(help_config=help_config)
|
|
96
|
+
@click.pass_context
|
|
97
|
+
def main(
|
|
98
|
+
ctx: click.Context,
|
|
99
|
+
endpoint: str | None,
|
|
100
|
+
insecure: bool,
|
|
101
|
+
verbose: int,
|
|
102
|
+
org: str | None,
|
|
103
|
+
config_file: str | None,
|
|
104
|
+
):
|
|
105
|
+
"""
|
|
106
|
+
The Flyte CLI is the command line interface for working with the Flyte SDK and backend.
|
|
107
|
+
|
|
108
|
+
It follows a simple verb/noun structure,
|
|
109
|
+
where the top-level commands are verbs that describe the action to be taken,
|
|
110
|
+
and the subcommands are nouns that describe the object of the action.
|
|
111
|
+
|
|
112
|
+
The root command can be used to configure the CLI for persistent settings,
|
|
113
|
+
such as the endpoint, organization, and verbosity level.
|
|
114
|
+
|
|
115
|
+
Set endpoint and organization:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
$ flyte --endpoint <endpoint> --org <org> get project <project_name>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Increase verbosity level (This is useful for debugging,
|
|
122
|
+
this will show more logs and exception traces):
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
$ flyte -vvv get logs <run-name>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Override the default config file:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
$ flyte --config /path/to/config.yaml run ...
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
* [Documentation](https://www.union.ai/docs/flyte/user-guide/)
|
|
135
|
+
* [GitHub](https://github.com/flyteorg/flyte): Please leave a star if you like Flyte!
|
|
136
|
+
* [Slack](https://slack.flyte.org): Join the community and ask questions.
|
|
137
|
+
* [Issues](https://github.com/flyteorg/flyte/issues)
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
import flyte.config as config
|
|
141
|
+
|
|
142
|
+
log_level = _verbosity_to_loglevel(verbose)
|
|
143
|
+
if log_level is not None:
|
|
144
|
+
initialize_logger(log_level)
|
|
145
|
+
|
|
146
|
+
cfg = config.auto(config_file=config_file)
|
|
147
|
+
if cfg.source:
|
|
148
|
+
logger.debug(f"Using config file discovered at location `{cfg.source.absolute()}`")
|
|
149
|
+
|
|
150
|
+
ctx.obj = CLIConfig(
|
|
151
|
+
log_level=log_level,
|
|
152
|
+
endpoint=endpoint,
|
|
153
|
+
insecure=insecure,
|
|
154
|
+
org=org,
|
|
155
|
+
config=cfg,
|
|
156
|
+
ctx=ctx,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
main.add_command(run)
|
|
161
|
+
main.add_command(deploy)
|
|
162
|
+
main.add_command(get) # type: ignore
|
|
163
|
+
main.add_command(create) # type: ignore
|
|
164
|
+
main.add_command(abort) # type: ignore
|
|
165
|
+
main.add_command(gen) # type: ignore
|
|
166
|
+
main.add_command(delete) # type: ignore
|
flyte/config/__init__.py
ADDED
flyte/config/_config.py
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import os
|
|
5
|
+
import pathlib
|
|
6
|
+
import typing
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
import rich.repr
|
|
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"]
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from flyte.remote._client.auth import AuthType
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@rich.repr.auto
|
|
23
|
+
@dataclass(init=True, repr=True, eq=True, frozen=True)
|
|
24
|
+
class PlatformConfig(object):
|
|
25
|
+
"""
|
|
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
|
|
43
|
+
"""
|
|
44
|
+
|
|
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)
|
|
119
|
+
|
|
120
|
+
|
|
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":
|
|
130
|
+
"""
|
|
131
|
+
Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
|
|
132
|
+
:param config_file:
|
|
133
|
+
:return:
|
|
134
|
+
"""
|
|
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 Config(object):
|
|
146
|
+
"""
|
|
147
|
+
This the parent configuration object and holds all the underlying configuration object types. An instance of
|
|
148
|
+
this object holds all the config necessary to
|
|
149
|
+
|
|
150
|
+
1. Interactive session with Flyte backend
|
|
151
|
+
2. Some parts are required for Serialization, for example Platform Config is not required
|
|
152
|
+
3. Runtime of a task
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
platform: PlatformConfig = field(default=PlatformConfig())
|
|
156
|
+
task: TaskConfig = field(default=TaskConfig())
|
|
157
|
+
source: pathlib.Path | None = None
|
|
158
|
+
|
|
159
|
+
def with_params(
|
|
160
|
+
self,
|
|
161
|
+
platform: PlatformConfig | None = None,
|
|
162
|
+
task: TaskConfig | None = None,
|
|
163
|
+
) -> "Config":
|
|
164
|
+
return Config(
|
|
165
|
+
platform=platform or self.platform,
|
|
166
|
+
task=task or self.task,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
@classmethod
|
|
170
|
+
def auto(cls, config_file: typing.Union[str, ConfigFile, None] = None) -> "Config":
|
|
171
|
+
"""
|
|
172
|
+
Automatically constructs the Config Object. The order of precedence is as follows
|
|
173
|
+
1. first try to find any env vars that match the config vars specified in the FLYTE_CONFIG format.
|
|
174
|
+
2. If not found in environment then values ar read from the config file
|
|
175
|
+
3. If not found in the file, then the default values are used.
|
|
176
|
+
|
|
177
|
+
:param config_file: file path to read the config from, if not specified default locations are searched
|
|
178
|
+
:return: Config
|
|
179
|
+
"""
|
|
180
|
+
config_file = get_config_file(config_file)
|
|
181
|
+
if config_file is None:
|
|
182
|
+
logger.debug("No config file found, using default values")
|
|
183
|
+
return Config()
|
|
184
|
+
return Config(
|
|
185
|
+
platform=PlatformConfig.auto(config_file), task=TaskConfig.auto(config_file), source=config_file.path
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def set_if_exists(d: dict, k: str, val: typing.Any) -> dict:
|
|
190
|
+
"""
|
|
191
|
+
Given a dict ``d`` sets the key ``k`` with value of config ``v``, if the config value ``v`` is set
|
|
192
|
+
and return the updated dictionary.
|
|
193
|
+
"""
|
|
194
|
+
exists = isinstance(val, bool) or bool(val is not None and val)
|
|
195
|
+
if exists:
|
|
196
|
+
d[k] = val
|
|
197
|
+
return d
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def auto(config_file: typing.Union[str, ConfigFile, None] = None) -> Config:
|
|
201
|
+
"""
|
|
202
|
+
Automatically constructs the Config Object. The order of precedence is as follows
|
|
203
|
+
1. If specified, read the config from the provided file path.
|
|
204
|
+
2. If not specified, the config file is searched in the default locations.
|
|
205
|
+
a. ./config.yaml if it exists (current working directory)
|
|
206
|
+
b. `UCTL_CONFIG` environment variable
|
|
207
|
+
c. `FLYTECTL_CONFIG` environment variable
|
|
208
|
+
d. ~/.union/config.yaml if it exists
|
|
209
|
+
e. ~/.flyte/config.yaml if it exists
|
|
210
|
+
3. If any value is not found in the config file, the default value is used.
|
|
211
|
+
4. For any value there are environment variables that match the config variable names, those will override
|
|
212
|
+
|
|
213
|
+
:param config_file: file path to read the config from, if not specified default locations are searched
|
|
214
|
+
:return: Config
|
|
215
|
+
"""
|
|
216
|
+
return Config.auto(config_file)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from flyte.config._reader 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"))
|