truefoundry 0.2.10__py3-none-any.whl → 0.3.0rc2__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 truefoundry might be problematic. Click here for more details.
- truefoundry/__init__.py +1 -0
- truefoundry/autodeploy/cli.py +31 -18
- truefoundry/deploy/__init__.py +119 -1
- truefoundry/deploy/auto_gen/models.py +1791 -0
- truefoundry/deploy/builder/__init__.py +138 -0
- truefoundry/deploy/builder/builders/__init__.py +22 -0
- truefoundry/deploy/builder/builders/dockerfile.py +57 -0
- truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py +44 -0
- truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py +51 -0
- truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py +44 -0
- truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py +158 -0
- truefoundry/deploy/builder/docker_service.py +168 -0
- truefoundry/deploy/cli/cli.py +19 -26
- truefoundry/deploy/cli/commands/__init__.py +18 -0
- truefoundry/deploy/cli/commands/apply_command.py +52 -0
- truefoundry/deploy/cli/commands/build_command.py +45 -0
- truefoundry/deploy/cli/commands/build_logs_command.py +89 -0
- truefoundry/deploy/cli/commands/create_command.py +75 -0
- truefoundry/deploy/cli/commands/delete_command.py +77 -0
- truefoundry/deploy/cli/commands/deploy_command.py +99 -0
- truefoundry/deploy/cli/commands/get_command.py +216 -0
- truefoundry/deploy/cli/commands/list_command.py +171 -0
- truefoundry/deploy/cli/commands/login_command.py +33 -0
- truefoundry/deploy/cli/commands/logout_command.py +20 -0
- truefoundry/deploy/cli/commands/logs_command.py +134 -0
- truefoundry/deploy/cli/commands/patch_application_command.py +79 -0
- truefoundry/deploy/cli/commands/patch_command.py +70 -0
- truefoundry/deploy/cli/commands/redeploy_command.py +41 -0
- truefoundry/deploy/cli/commands/terminate_comand.py +44 -0
- truefoundry/deploy/cli/commands/trigger_command.py +87 -0
- truefoundry/deploy/cli/config.py +10 -0
- truefoundry/deploy/cli/console.py +5 -0
- truefoundry/deploy/cli/const.py +12 -0
- truefoundry/deploy/cli/display_util.py +118 -0
- truefoundry/deploy/cli/util.py +92 -0
- truefoundry/deploy/core/__init__.py +7 -0
- truefoundry/deploy/core/login.py +9 -0
- truefoundry/deploy/core/logout.py +5 -0
- truefoundry/deploy/function_service/__init__.py +3 -0
- truefoundry/deploy/function_service/__main__.py +27 -0
- truefoundry/deploy/function_service/app.py +92 -0
- truefoundry/deploy/function_service/build.py +45 -0
- truefoundry/deploy/function_service/remote/__init__.py +6 -0
- truefoundry/deploy/function_service/remote/context.py +3 -0
- truefoundry/deploy/function_service/remote/method.py +67 -0
- truefoundry/deploy/function_service/remote/remote.py +144 -0
- truefoundry/deploy/function_service/route.py +137 -0
- truefoundry/deploy/function_service/service.py +113 -0
- truefoundry/deploy/function_service/utils.py +53 -0
- truefoundry/deploy/io/__init__.py +0 -0
- truefoundry/deploy/io/output_callback.py +23 -0
- truefoundry/deploy/io/rich_output_callback.py +27 -0
- truefoundry/deploy/json_util.py +7 -0
- truefoundry/deploy/lib/__init__.py +0 -0
- truefoundry/deploy/lib/auth/auth_service_client.py +81 -0
- truefoundry/deploy/lib/auth/credential_file_manager.py +115 -0
- truefoundry/deploy/lib/auth/credential_provider.py +131 -0
- truefoundry/deploy/lib/auth/servicefoundry_session.py +59 -0
- truefoundry/deploy/lib/clients/__init__.py +0 -0
- truefoundry/deploy/lib/clients/servicefoundry_client.py +723 -0
- truefoundry/deploy/lib/clients/shell_client.py +13 -0
- truefoundry/deploy/lib/clients/utils.py +41 -0
- truefoundry/deploy/lib/const.py +43 -0
- truefoundry/deploy/lib/dao/__init__.py +0 -0
- truefoundry/deploy/lib/dao/application.py +246 -0
- truefoundry/deploy/lib/dao/apply.py +80 -0
- truefoundry/deploy/lib/dao/version.py +33 -0
- truefoundry/deploy/lib/dao/workspace.py +71 -0
- truefoundry/deploy/lib/exceptions.py +23 -0
- truefoundry/deploy/lib/logs_utils.py +43 -0
- truefoundry/deploy/lib/messages.py +12 -0
- truefoundry/deploy/lib/model/__init__.py +0 -0
- truefoundry/deploy/lib/model/entity.py +382 -0
- truefoundry/deploy/lib/session.py +146 -0
- truefoundry/deploy/lib/util.py +70 -0
- truefoundry/deploy/lib/win32.py +129 -0
- truefoundry/deploy/v2/__init__.py +0 -0
- truefoundry/deploy/v2/lib/__init__.py +3 -0
- truefoundry/deploy/v2/lib/deploy.py +232 -0
- truefoundry/deploy/v2/lib/deployable_patched_models.py +72 -0
- truefoundry/deploy/v2/lib/models.py +53 -0
- truefoundry/deploy/v2/lib/patched_models.py +515 -0
- truefoundry/deploy/v2/lib/source.py +267 -0
- truefoundry/flyte/__init__.py +6 -0
- truefoundry/langchain/__init__.py +12 -1
- truefoundry/langchain/deprecated.py +302 -0
- truefoundry/langchain/truefoundry_chat.py +130 -0
- truefoundry/langchain/truefoundry_embeddings.py +171 -0
- truefoundry/langchain/truefoundry_llm.py +106 -0
- truefoundry/langchain/utils.py +85 -0
- truefoundry/logger.py +17 -0
- truefoundry/pydantic_v1.py +5 -0
- truefoundry/python_deploy_codegen.py +132 -0
- {truefoundry-0.2.10.dist-info → truefoundry-0.3.0rc2.dist-info}/METADATA +25 -6
- truefoundry-0.3.0rc2.dist-info/RECORD +125 -0
- truefoundry/deploy/cli/deploy.py +0 -165
- truefoundry-0.2.10.dist-info/RECORD +0 -38
- /truefoundry/{deploy/cli/version.py → version.py} +0 -0
- {truefoundry-0.2.10.dist-info → truefoundry-0.3.0rc2.dist-info}/WHEEL +0 -0
- {truefoundry-0.2.10.dist-info → truefoundry-0.3.0rc2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import sys
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
import rich_click as click
|
|
6
|
+
import yaml
|
|
7
|
+
from rich.pretty import pprint
|
|
8
|
+
|
|
9
|
+
from truefoundry.deploy.cli.config import CliConfig
|
|
10
|
+
from truefoundry.deploy.cli.console import console
|
|
11
|
+
from truefoundry.deploy.cli.const import COMMAND_CLS, GROUP_CLS
|
|
12
|
+
from truefoundry.deploy.cli.display_util import print_entity_obj, print_json
|
|
13
|
+
from truefoundry.deploy.cli.util import handle_exception_wrapper
|
|
14
|
+
from truefoundry.deploy.lib.dao import application as application_lib
|
|
15
|
+
from truefoundry.deploy.lib.dao import version as version_lib
|
|
16
|
+
from truefoundry.deploy.lib.dao import workspace as workspace_lib
|
|
17
|
+
|
|
18
|
+
# TODO (chiragjn): --json should disable all non json console prints
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@click.group(name="get", cls=GROUP_CLS)
|
|
22
|
+
def get_command():
|
|
23
|
+
# TODO (chiragjn): Figure out a way to update supported resources based on ENABLE_* flags
|
|
24
|
+
"""
|
|
25
|
+
Get TrueFoundry resources
|
|
26
|
+
|
|
27
|
+
\b
|
|
28
|
+
Supported resources:
|
|
29
|
+
- Workspace
|
|
30
|
+
- Application
|
|
31
|
+
- Application Version
|
|
32
|
+
"""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@click.command(name="workspace", cls=COMMAND_CLS, help="Get Workspace details")
|
|
37
|
+
@click.option(
|
|
38
|
+
"-w",
|
|
39
|
+
"--workspace-fqn",
|
|
40
|
+
"--workspace_fqn",
|
|
41
|
+
type=click.STRING,
|
|
42
|
+
default=None,
|
|
43
|
+
help="FQN of the Workspace",
|
|
44
|
+
required=True,
|
|
45
|
+
)
|
|
46
|
+
@handle_exception_wrapper
|
|
47
|
+
def get_workspace(workspace_fqn):
|
|
48
|
+
workspace = workspace_lib.get_workspace_by_fqn(workspace_fqn=workspace_fqn)
|
|
49
|
+
if CliConfig.get("json"):
|
|
50
|
+
print_json(data=workspace.dict())
|
|
51
|
+
else:
|
|
52
|
+
print_entity_obj("Workspace", workspace)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@click.command(name="application", cls=COMMAND_CLS, help="Get Application details")
|
|
56
|
+
@click.option(
|
|
57
|
+
"--application-fqn",
|
|
58
|
+
"--application_fqn",
|
|
59
|
+
type=click.STRING,
|
|
60
|
+
default=None,
|
|
61
|
+
help="FQN of the application",
|
|
62
|
+
required=True,
|
|
63
|
+
)
|
|
64
|
+
@handle_exception_wrapper
|
|
65
|
+
def get_application(application_fqn):
|
|
66
|
+
application = application_lib.get_application(application_fqn=application_fqn)
|
|
67
|
+
if CliConfig.get("json"):
|
|
68
|
+
print_json(data=application.dict())
|
|
69
|
+
else:
|
|
70
|
+
print_entity_obj(
|
|
71
|
+
"Application",
|
|
72
|
+
application,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@click.command(
|
|
77
|
+
name="application-version", cls=COMMAND_CLS, help="Get Application Version details"
|
|
78
|
+
)
|
|
79
|
+
@click.option(
|
|
80
|
+
"--application-fqn",
|
|
81
|
+
"--application_fqn",
|
|
82
|
+
type=click.STRING,
|
|
83
|
+
default=None,
|
|
84
|
+
help="FQN of the application",
|
|
85
|
+
required=True,
|
|
86
|
+
)
|
|
87
|
+
@click.option(
|
|
88
|
+
"--version",
|
|
89
|
+
type=click.STRING,
|
|
90
|
+
default=None,
|
|
91
|
+
help="Version number of the application deployment",
|
|
92
|
+
required=True,
|
|
93
|
+
)
|
|
94
|
+
@handle_exception_wrapper
|
|
95
|
+
def get_version(application_fqn, version):
|
|
96
|
+
version = version_lib.get_version(application_fqn=application_fqn, version=version)
|
|
97
|
+
if CliConfig.get("json"):
|
|
98
|
+
print_json(data=version.dict())
|
|
99
|
+
else:
|
|
100
|
+
print_entity_obj("Version", version)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@click.command(
|
|
104
|
+
name="spec", cls=COMMAND_CLS, help="Get YAML/Python Spec for an Application Version"
|
|
105
|
+
)
|
|
106
|
+
@click.option(
|
|
107
|
+
"--application-fqn",
|
|
108
|
+
"--application_fqn",
|
|
109
|
+
type=click.STRING,
|
|
110
|
+
default=None,
|
|
111
|
+
help="FQN of the application",
|
|
112
|
+
required=True,
|
|
113
|
+
)
|
|
114
|
+
@click.option(
|
|
115
|
+
"--version",
|
|
116
|
+
type=click.STRING,
|
|
117
|
+
default=None,
|
|
118
|
+
help="Version number of the application deployment",
|
|
119
|
+
required=True,
|
|
120
|
+
)
|
|
121
|
+
@click.option(
|
|
122
|
+
"-o",
|
|
123
|
+
"--output",
|
|
124
|
+
type=click.Choice(
|
|
125
|
+
[
|
|
126
|
+
"yml",
|
|
127
|
+
"yaml",
|
|
128
|
+
"json",
|
|
129
|
+
"py",
|
|
130
|
+
"python",
|
|
131
|
+
]
|
|
132
|
+
),
|
|
133
|
+
default="yaml",
|
|
134
|
+
help="Output format for the spec",
|
|
135
|
+
required=False,
|
|
136
|
+
)
|
|
137
|
+
@handle_exception_wrapper
|
|
138
|
+
def get_spec(application_fqn, version, output):
|
|
139
|
+
version = version_lib.get_version(application_fqn=application_fqn, version=version)
|
|
140
|
+
if output in ["yml", "yaml"]:
|
|
141
|
+
yaml.safe_dump(version.manifest.dict(), sys.stdout, indent=2)
|
|
142
|
+
elif output in ["json"]:
|
|
143
|
+
print_json(version.manifest.dict())
|
|
144
|
+
elif output in ["py", "python"]:
|
|
145
|
+
from truefoundry.deploy.v2.lib.deployable_patched_models import Application
|
|
146
|
+
|
|
147
|
+
manifest = version.manifest.dict()
|
|
148
|
+
instance = Application.parse_obj(manifest).__root__
|
|
149
|
+
|
|
150
|
+
# TODO (chiragjn): Can we somehow just enable `use_enum_values` on all Pydantic classes?
|
|
151
|
+
|
|
152
|
+
@contextlib.contextmanager
|
|
153
|
+
def _monkey_patch_enum_repr():
|
|
154
|
+
def new_repr(self):
|
|
155
|
+
# return "%r" % (self._value_)
|
|
156
|
+
return "%s.%s" % (self.__class__.__name__, self._name_)
|
|
157
|
+
|
|
158
|
+
enum_subclasses = [
|
|
159
|
+
es
|
|
160
|
+
for es in Enum.__subclasses__()
|
|
161
|
+
if es.__module__.startswith("truefoundry.")
|
|
162
|
+
]
|
|
163
|
+
original_reprs = []
|
|
164
|
+
for es in enum_subclasses:
|
|
165
|
+
original_reprs.append(es)
|
|
166
|
+
es.__repr__ = new_repr
|
|
167
|
+
|
|
168
|
+
yield
|
|
169
|
+
|
|
170
|
+
for es, og_repr in zip(enum_subclasses, original_reprs):
|
|
171
|
+
es.__repr__ = og_repr
|
|
172
|
+
|
|
173
|
+
with _monkey_patch_enum_repr():
|
|
174
|
+
pprint(
|
|
175
|
+
instance,
|
|
176
|
+
indent_guides=False,
|
|
177
|
+
max_length=88,
|
|
178
|
+
expand_all=True,
|
|
179
|
+
console=console,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@click.command(name="job-run", cls=COMMAND_CLS, help="Get Job Run")
|
|
184
|
+
@click.option(
|
|
185
|
+
"--application-fqn",
|
|
186
|
+
"--application_fqn",
|
|
187
|
+
type=click.STRING,
|
|
188
|
+
default=None,
|
|
189
|
+
help="FQN of the application",
|
|
190
|
+
required=True,
|
|
191
|
+
)
|
|
192
|
+
@click.option(
|
|
193
|
+
"--job-run-name",
|
|
194
|
+
"--job_run_name",
|
|
195
|
+
type=click.STRING,
|
|
196
|
+
default=None,
|
|
197
|
+
help="Run name of the job",
|
|
198
|
+
required=True,
|
|
199
|
+
)
|
|
200
|
+
@handle_exception_wrapper
|
|
201
|
+
def get_job_run(application_fqn, job_run_name):
|
|
202
|
+
job_run = application_lib.get_job_run(
|
|
203
|
+
application_fqn=application_fqn, job_run_name=job_run_name
|
|
204
|
+
)
|
|
205
|
+
if CliConfig.get("json"):
|
|
206
|
+
print_json(data=job_run.dict())
|
|
207
|
+
else:
|
|
208
|
+
print_entity_obj("Job Run", job_run)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def get_get_command():
|
|
212
|
+
get_command.add_command(get_workspace)
|
|
213
|
+
get_command.add_command(get_application)
|
|
214
|
+
get_command.add_command(get_version)
|
|
215
|
+
get_command.add_command(get_job_run)
|
|
216
|
+
return get_command
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import rich_click as click
|
|
2
|
+
|
|
3
|
+
from truefoundry.deploy.cli.config import CliConfig
|
|
4
|
+
from truefoundry.deploy.cli.const import COMMAND_CLS, GROUP_CLS
|
|
5
|
+
from truefoundry.deploy.cli.display_util import print_entity_list, print_json
|
|
6
|
+
from truefoundry.deploy.cli.util import handle_exception_wrapper
|
|
7
|
+
from truefoundry.deploy.io.rich_output_callback import RichOutputCallBack
|
|
8
|
+
from truefoundry.deploy.lib.dao import application as application_lib
|
|
9
|
+
from truefoundry.deploy.lib.dao import version as version_lib
|
|
10
|
+
from truefoundry.deploy.lib.dao import workspace as workspace_lib
|
|
11
|
+
from truefoundry.deploy.lib.messages import (
|
|
12
|
+
PROMPT_NO_APPLICATIONS,
|
|
13
|
+
PROMPT_NO_VERSIONS,
|
|
14
|
+
PROMPT_NO_WORKSPACES,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# TODO (chiragjn): --json should disable all non json console prints
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.group(name="list", cls=GROUP_CLS)
|
|
21
|
+
def list_command():
|
|
22
|
+
# TODO (chiragjn): Figure out a way to update supported resources based on ENABLE_* flags
|
|
23
|
+
"""
|
|
24
|
+
List TrueFoundry resources
|
|
25
|
+
|
|
26
|
+
\b
|
|
27
|
+
Supported resources:
|
|
28
|
+
- Workspace
|
|
29
|
+
- Application
|
|
30
|
+
- Application Version
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@click.command(name="workspaces", cls=COMMAND_CLS, help="List Workspaces")
|
|
35
|
+
@click.option(
|
|
36
|
+
"-c",
|
|
37
|
+
"--cluster-name",
|
|
38
|
+
"--cluster_name",
|
|
39
|
+
type=click.STRING,
|
|
40
|
+
default=None,
|
|
41
|
+
help="Cluster name",
|
|
42
|
+
)
|
|
43
|
+
@handle_exception_wrapper
|
|
44
|
+
def list_workspaces(cluster_name):
|
|
45
|
+
workspaces = workspace_lib.list_workspaces(
|
|
46
|
+
cluster_name=cluster_name,
|
|
47
|
+
)
|
|
48
|
+
if not workspaces:
|
|
49
|
+
output_hook = RichOutputCallBack()
|
|
50
|
+
output_hook.print_line(PROMPT_NO_WORKSPACES)
|
|
51
|
+
else:
|
|
52
|
+
workspaces.sort(key=lambda s: s.createdAt, reverse=True)
|
|
53
|
+
|
|
54
|
+
print_entity_list(
|
|
55
|
+
"Workspaces",
|
|
56
|
+
workspaces,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@click.command(name="applications", cls=COMMAND_CLS, help="List Applications")
|
|
61
|
+
@click.option(
|
|
62
|
+
"-w",
|
|
63
|
+
"--workspace-fqn",
|
|
64
|
+
"--workspace_fqn",
|
|
65
|
+
type=click.STRING,
|
|
66
|
+
default=None,
|
|
67
|
+
help="FQN of the Workspace",
|
|
68
|
+
)
|
|
69
|
+
@click.option(
|
|
70
|
+
"--application-type",
|
|
71
|
+
"--application_type",
|
|
72
|
+
type=click.Choice(
|
|
73
|
+
[
|
|
74
|
+
"service",
|
|
75
|
+
"job",
|
|
76
|
+
"model-deployment",
|
|
77
|
+
"volume",
|
|
78
|
+
"notebook",
|
|
79
|
+
"intercept",
|
|
80
|
+
"helm",
|
|
81
|
+
"all",
|
|
82
|
+
]
|
|
83
|
+
),
|
|
84
|
+
default="all",
|
|
85
|
+
help="Application Type",
|
|
86
|
+
)
|
|
87
|
+
@handle_exception_wrapper
|
|
88
|
+
def list_applications(workspace_fqn, application_type):
|
|
89
|
+
applications = application_lib.list_applications(
|
|
90
|
+
workspace_fqn=workspace_fqn, application_type=application_type
|
|
91
|
+
)
|
|
92
|
+
if not applications:
|
|
93
|
+
output_hook = RichOutputCallBack()
|
|
94
|
+
output_hook.print_line(PROMPT_NO_APPLICATIONS)
|
|
95
|
+
else:
|
|
96
|
+
applications.sort(key=lambda s: s.createdAt, reverse=True)
|
|
97
|
+
|
|
98
|
+
print_entity_list(
|
|
99
|
+
"Applications",
|
|
100
|
+
applications,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@click.command(
|
|
105
|
+
name="application-versions", cls=COMMAND_CLS, help="List Application Versions"
|
|
106
|
+
)
|
|
107
|
+
@click.option(
|
|
108
|
+
"--application-fqn",
|
|
109
|
+
"--application_fqn",
|
|
110
|
+
type=click.STRING,
|
|
111
|
+
default=None,
|
|
112
|
+
help="FQN of the application",
|
|
113
|
+
required=True,
|
|
114
|
+
)
|
|
115
|
+
@handle_exception_wrapper
|
|
116
|
+
def list_versions(application_fqn):
|
|
117
|
+
versions = version_lib.list_versions(
|
|
118
|
+
application_fqn=application_fqn,
|
|
119
|
+
)
|
|
120
|
+
if not versions:
|
|
121
|
+
output_hook = RichOutputCallBack()
|
|
122
|
+
output_hook.print_line(PROMPT_NO_VERSIONS)
|
|
123
|
+
else:
|
|
124
|
+
versions.sort(key=lambda s: s.createdAt, reverse=True)
|
|
125
|
+
|
|
126
|
+
print_entity_list(
|
|
127
|
+
"Application Versions",
|
|
128
|
+
versions,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@click.command(name="job-run", cls=COMMAND_CLS, help="List Job Runs")
|
|
133
|
+
@click.option(
|
|
134
|
+
"--application-fqn",
|
|
135
|
+
"--application_fqn",
|
|
136
|
+
type=click.STRING,
|
|
137
|
+
default=None,
|
|
138
|
+
help="FQN of the application",
|
|
139
|
+
required=True,
|
|
140
|
+
)
|
|
141
|
+
@click.option(
|
|
142
|
+
"--max-results",
|
|
143
|
+
"--max_results",
|
|
144
|
+
type=click.STRING,
|
|
145
|
+
default=None,
|
|
146
|
+
help="Maximum number of Runs to fetch",
|
|
147
|
+
)
|
|
148
|
+
@click.option(
|
|
149
|
+
"--offset",
|
|
150
|
+
type=click.STRING,
|
|
151
|
+
default=None,
|
|
152
|
+
help="Number of Runs to skip",
|
|
153
|
+
)
|
|
154
|
+
@handle_exception_wrapper
|
|
155
|
+
def list_job_runs(application_fqn, max_results, offset):
|
|
156
|
+
job_runs = application_lib.list_job_runs(
|
|
157
|
+
application_fqn=application_fqn, max_results=max_results, offset=offset
|
|
158
|
+
)
|
|
159
|
+
if CliConfig.get("json"):
|
|
160
|
+
print_json(data=job_runs.dict())
|
|
161
|
+
else:
|
|
162
|
+
print_entity_list("Job Runs", job_runs)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def get_list_command():
|
|
166
|
+
list_command.add_command(list_workspaces)
|
|
167
|
+
list_command.add_command(list_applications)
|
|
168
|
+
list_command.add_command(list_versions)
|
|
169
|
+
list_command.add_command(list_job_runs)
|
|
170
|
+
|
|
171
|
+
return list_command
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import rich_click as click
|
|
2
|
+
|
|
3
|
+
from truefoundry.deploy.cli.const import COMMAND_CLS
|
|
4
|
+
from truefoundry.deploy.cli.util import (
|
|
5
|
+
_prompt_if_no_value_and_supported,
|
|
6
|
+
handle_exception_wrapper,
|
|
7
|
+
)
|
|
8
|
+
from truefoundry.deploy.io.rich_output_callback import RichOutputCallBack
|
|
9
|
+
from truefoundry.deploy.lib.const import HOST_ENV_NAME
|
|
10
|
+
from truefoundry.deploy.lib.session import login
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.command(name="login", cls=COMMAND_CLS)
|
|
14
|
+
@click.option("--relogin", type=click.BOOL, is_flag=True, default=False)
|
|
15
|
+
@click.option("--host", type=click.STRING, required=True, envvar=HOST_ENV_NAME)
|
|
16
|
+
@click.option(
|
|
17
|
+
"--api-key",
|
|
18
|
+
"--api_key",
|
|
19
|
+
type=click.STRING,
|
|
20
|
+
default=None,
|
|
21
|
+
**_prompt_if_no_value_and_supported(prompt="API Key", hide_input=True),
|
|
22
|
+
)
|
|
23
|
+
@handle_exception_wrapper
|
|
24
|
+
def login_command(relogin: bool, host: str, api_key: str):
|
|
25
|
+
"""
|
|
26
|
+
Login to TrueFoundry
|
|
27
|
+
"""
|
|
28
|
+
callback = RichOutputCallBack()
|
|
29
|
+
login(api_key=api_key, host=host, relogin=relogin, output_hook=callback)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_login_command():
|
|
33
|
+
return login_command
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import rich_click as click
|
|
2
|
+
|
|
3
|
+
from truefoundry.deploy.cli.const import COMMAND_CLS
|
|
4
|
+
from truefoundry.deploy.cli.util import handle_exception_wrapper
|
|
5
|
+
from truefoundry.deploy.io.rich_output_callback import RichOutputCallBack
|
|
6
|
+
from truefoundry.deploy.lib.session import logout
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command(name="logout", cls=COMMAND_CLS)
|
|
10
|
+
@handle_exception_wrapper
|
|
11
|
+
def logout_command():
|
|
12
|
+
"""
|
|
13
|
+
Logout from current TrueFoundry session
|
|
14
|
+
"""
|
|
15
|
+
callback = RichOutputCallBack()
|
|
16
|
+
logout(output_hook=callback)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_logout_command():
|
|
20
|
+
return logout_command
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import rich_click as click
|
|
5
|
+
from dateutil.tz import tzlocal
|
|
6
|
+
|
|
7
|
+
from truefoundry.deploy.cli.const import COMMAND_CLS
|
|
8
|
+
from truefoundry.deploy.cli.util import handle_exception_wrapper
|
|
9
|
+
from truefoundry.deploy.io.rich_output_callback import RichOutputCallBack
|
|
10
|
+
from truefoundry.deploy.lib.clients.servicefoundry_client import (
|
|
11
|
+
ServiceFoundryServiceClient,
|
|
12
|
+
)
|
|
13
|
+
from truefoundry.deploy.lib.logs_utils import get_timestamp_from_timestamp_or_duration
|
|
14
|
+
from truefoundry.deploy.lib.util import get_deployment_fqn_from_application_fqn
|
|
15
|
+
from truefoundry.logger import logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command(name="logs", cls=COMMAND_CLS)
|
|
19
|
+
@click.option(
|
|
20
|
+
"--application-fqn",
|
|
21
|
+
type=click.STRING,
|
|
22
|
+
help="FQN of the application",
|
|
23
|
+
required=True,
|
|
24
|
+
)
|
|
25
|
+
@click.option(
|
|
26
|
+
"--job-run-name",
|
|
27
|
+
"--job_run_name",
|
|
28
|
+
type=click.STRING,
|
|
29
|
+
default=None,
|
|
30
|
+
help="Run name of the job (if application is a job)",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"--version",
|
|
34
|
+
type=click.INT,
|
|
35
|
+
help="Version number of the application deployment",
|
|
36
|
+
default=None,
|
|
37
|
+
)
|
|
38
|
+
@click.option(
|
|
39
|
+
"--since",
|
|
40
|
+
type=click.STRING,
|
|
41
|
+
help="Show logs since timestamp (e.g.2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)",
|
|
42
|
+
default="2h",
|
|
43
|
+
)
|
|
44
|
+
@click.option(
|
|
45
|
+
"--until",
|
|
46
|
+
type=click.STRING,
|
|
47
|
+
help="Show logs until timestamp (e.g.2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)",
|
|
48
|
+
default=None,
|
|
49
|
+
)
|
|
50
|
+
@click.option(
|
|
51
|
+
"-n", "--tail", type=click.INT, help="Number of logs to tail", default=None
|
|
52
|
+
)
|
|
53
|
+
@click.option("-f", "--follow", help="Follow log output", is_flag=True, default=False)
|
|
54
|
+
@handle_exception_wrapper
|
|
55
|
+
def logs_command(
|
|
56
|
+
application_fqn: str,
|
|
57
|
+
job_run_name: Optional[str],
|
|
58
|
+
version: Optional[int],
|
|
59
|
+
since: str,
|
|
60
|
+
until: Optional[str],
|
|
61
|
+
tail: Optional[int],
|
|
62
|
+
follow: bool,
|
|
63
|
+
) -> None:
|
|
64
|
+
"""
|
|
65
|
+
Get logs for Application
|
|
66
|
+
"""
|
|
67
|
+
start_ts = get_timestamp_from_timestamp_or_duration(since)
|
|
68
|
+
end_ts = (
|
|
69
|
+
get_timestamp_from_timestamp_or_duration(until)
|
|
70
|
+
if until
|
|
71
|
+
else datetime.now().timestamp() * 1000
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
output_hook = RichOutputCallBack()
|
|
75
|
+
tfs_client = ServiceFoundryServiceClient()
|
|
76
|
+
|
|
77
|
+
if version:
|
|
78
|
+
deployment_fqn = get_deployment_fqn_from_application_fqn(
|
|
79
|
+
application_fqn=application_fqn, version=version
|
|
80
|
+
)
|
|
81
|
+
deployment_fqn_response = tfs_client.get_deployment_info_by_fqn(deployment_fqn)
|
|
82
|
+
workspace_id, application_id, deployment_id = (
|
|
83
|
+
deployment_fqn_response.workspaceId,
|
|
84
|
+
deployment_fqn_response.applicationId,
|
|
85
|
+
deployment_fqn_response.deploymentId,
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
app_fqn_response = tfs_client.get_application_info_by_fqn(application_fqn)
|
|
89
|
+
workspace_id, application_id, deployment_id = (
|
|
90
|
+
app_fqn_response.workspaceId,
|
|
91
|
+
app_fqn_response.applicationId,
|
|
92
|
+
None,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if until:
|
|
96
|
+
logger.info(
|
|
97
|
+
"Fetching logs from %s to %s for application fqn: %s",
|
|
98
|
+
datetime.fromtimestamp(start_ts / 1000, tzlocal()).isoformat(),
|
|
99
|
+
datetime.fromtimestamp(end_ts / 1000, tzlocal()).isoformat(),
|
|
100
|
+
application_fqn,
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
logger.info(
|
|
104
|
+
"Fetching logs from %s for application fqn: %s",
|
|
105
|
+
datetime.fromtimestamp(start_ts / 1000, tzlocal()).isoformat(),
|
|
106
|
+
application_fqn,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if until or not follow:
|
|
110
|
+
tfs_client.fetch_deployment_logs(
|
|
111
|
+
workspace_id=workspace_id,
|
|
112
|
+
application_id=application_id,
|
|
113
|
+
deployment_id=deployment_id,
|
|
114
|
+
job_run_name=job_run_name,
|
|
115
|
+
start_ts=start_ts,
|
|
116
|
+
end_ts=end_ts,
|
|
117
|
+
limit=tail,
|
|
118
|
+
callback=output_hook,
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
tfs_client.poll_logs_for_deployment(
|
|
122
|
+
workspace_id=workspace_id,
|
|
123
|
+
application_id=application_id,
|
|
124
|
+
deployment_id=deployment_id,
|
|
125
|
+
job_run_name=job_run_name,
|
|
126
|
+
start_ts=start_ts,
|
|
127
|
+
limit=tail,
|
|
128
|
+
poll_interval_seconds=5,
|
|
129
|
+
callback=output_hook,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def get_logs_command():
|
|
134
|
+
return logs_command
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
import rich_click as click
|
|
4
|
+
import yaml
|
|
5
|
+
|
|
6
|
+
from truefoundry.deploy.cli.const import GROUP_CLS
|
|
7
|
+
from truefoundry.deploy.lib.dao import application as application_lib
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.group(
|
|
11
|
+
name="patch-application",
|
|
12
|
+
cls=GROUP_CLS,
|
|
13
|
+
invoke_without_command=True,
|
|
14
|
+
help="Deploy application with patches to Truefoundry",
|
|
15
|
+
)
|
|
16
|
+
@click.option(
|
|
17
|
+
"-f",
|
|
18
|
+
"--patch-file",
|
|
19
|
+
"--patch_file",
|
|
20
|
+
type=click.Path(exists=True, dir_okay=False, resolve_path=True),
|
|
21
|
+
help="Path to yaml patch file",
|
|
22
|
+
show_default=True,
|
|
23
|
+
)
|
|
24
|
+
@click.option(
|
|
25
|
+
"-p",
|
|
26
|
+
"--patch",
|
|
27
|
+
type=click.STRING,
|
|
28
|
+
help="Patch in JSON format provided as a string.",
|
|
29
|
+
show_default=True,
|
|
30
|
+
)
|
|
31
|
+
@click.option(
|
|
32
|
+
"-a",
|
|
33
|
+
"--application_fqn",
|
|
34
|
+
"--application-fqn",
|
|
35
|
+
type=click.STRING,
|
|
36
|
+
required=True,
|
|
37
|
+
help="FQN of the Application to patch and deploy",
|
|
38
|
+
)
|
|
39
|
+
@click.option(
|
|
40
|
+
"--wait/--no-wait",
|
|
41
|
+
"--wait/--no_wait",
|
|
42
|
+
is_flag=True,
|
|
43
|
+
show_default=True,
|
|
44
|
+
default=True,
|
|
45
|
+
help="Wait and tail the deployment progress",
|
|
46
|
+
)
|
|
47
|
+
def patch_application_command(
|
|
48
|
+
patch_file: str, application_fqn: str, patch: str, wait: bool
|
|
49
|
+
):
|
|
50
|
+
from truefoundry.deploy.v2.lib.deployable_patched_models import Application
|
|
51
|
+
|
|
52
|
+
manifest_patch_obj = None
|
|
53
|
+
if not patch_file and not patch:
|
|
54
|
+
raise Exception("You need to either provide --file or --patch.")
|
|
55
|
+
elif patch and patch_file:
|
|
56
|
+
raise Exception("You can only provide one of --file and --patch")
|
|
57
|
+
elif patch:
|
|
58
|
+
try:
|
|
59
|
+
manifest_patch_obj = json.loads(patch)
|
|
60
|
+
except json.decoder.JSONDecodeError as e:
|
|
61
|
+
raise Exception("Invalid JSON provided as --patch") from e
|
|
62
|
+
elif patch_file:
|
|
63
|
+
with open(patch_file, "r") as f:
|
|
64
|
+
manifest_patch_obj = yaml.safe_load(f)
|
|
65
|
+
|
|
66
|
+
if not manifest_patch_obj or not isinstance(manifest_patch_obj, dict):
|
|
67
|
+
raise Exception("Invalid patch, aborting deployment.")
|
|
68
|
+
|
|
69
|
+
tfy_application = application_lib.get_application(application_fqn=application_fqn)
|
|
70
|
+
patched_application_obj = application_lib.get_patched_application_definition(
|
|
71
|
+
application=tfy_application, manifest_patch=manifest_patch_obj
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
application = Application.parse_obj(patched_application_obj)
|
|
75
|
+
application.deploy(workspace_fqn=tfy_application.workspace.fqn, wait=wait)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_patch_application_command():
|
|
79
|
+
return patch_application_command
|