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.

Files changed (100) hide show
  1. truefoundry/__init__.py +1 -0
  2. truefoundry/autodeploy/cli.py +31 -18
  3. truefoundry/deploy/__init__.py +119 -1
  4. truefoundry/deploy/auto_gen/models.py +1791 -0
  5. truefoundry/deploy/builder/__init__.py +138 -0
  6. truefoundry/deploy/builder/builders/__init__.py +22 -0
  7. truefoundry/deploy/builder/builders/dockerfile.py +57 -0
  8. truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py +44 -0
  9. truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py +51 -0
  10. truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py +44 -0
  11. truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py +158 -0
  12. truefoundry/deploy/builder/docker_service.py +168 -0
  13. truefoundry/deploy/cli/cli.py +19 -26
  14. truefoundry/deploy/cli/commands/__init__.py +18 -0
  15. truefoundry/deploy/cli/commands/apply_command.py +52 -0
  16. truefoundry/deploy/cli/commands/build_command.py +45 -0
  17. truefoundry/deploy/cli/commands/build_logs_command.py +89 -0
  18. truefoundry/deploy/cli/commands/create_command.py +75 -0
  19. truefoundry/deploy/cli/commands/delete_command.py +77 -0
  20. truefoundry/deploy/cli/commands/deploy_command.py +99 -0
  21. truefoundry/deploy/cli/commands/get_command.py +216 -0
  22. truefoundry/deploy/cli/commands/list_command.py +171 -0
  23. truefoundry/deploy/cli/commands/login_command.py +33 -0
  24. truefoundry/deploy/cli/commands/logout_command.py +20 -0
  25. truefoundry/deploy/cli/commands/logs_command.py +134 -0
  26. truefoundry/deploy/cli/commands/patch_application_command.py +79 -0
  27. truefoundry/deploy/cli/commands/patch_command.py +70 -0
  28. truefoundry/deploy/cli/commands/redeploy_command.py +41 -0
  29. truefoundry/deploy/cli/commands/terminate_comand.py +44 -0
  30. truefoundry/deploy/cli/commands/trigger_command.py +87 -0
  31. truefoundry/deploy/cli/config.py +10 -0
  32. truefoundry/deploy/cli/console.py +5 -0
  33. truefoundry/deploy/cli/const.py +12 -0
  34. truefoundry/deploy/cli/display_util.py +118 -0
  35. truefoundry/deploy/cli/util.py +92 -0
  36. truefoundry/deploy/core/__init__.py +7 -0
  37. truefoundry/deploy/core/login.py +9 -0
  38. truefoundry/deploy/core/logout.py +5 -0
  39. truefoundry/deploy/function_service/__init__.py +3 -0
  40. truefoundry/deploy/function_service/__main__.py +27 -0
  41. truefoundry/deploy/function_service/app.py +92 -0
  42. truefoundry/deploy/function_service/build.py +45 -0
  43. truefoundry/deploy/function_service/remote/__init__.py +6 -0
  44. truefoundry/deploy/function_service/remote/context.py +3 -0
  45. truefoundry/deploy/function_service/remote/method.py +67 -0
  46. truefoundry/deploy/function_service/remote/remote.py +144 -0
  47. truefoundry/deploy/function_service/route.py +137 -0
  48. truefoundry/deploy/function_service/service.py +113 -0
  49. truefoundry/deploy/function_service/utils.py +53 -0
  50. truefoundry/deploy/io/__init__.py +0 -0
  51. truefoundry/deploy/io/output_callback.py +23 -0
  52. truefoundry/deploy/io/rich_output_callback.py +27 -0
  53. truefoundry/deploy/json_util.py +7 -0
  54. truefoundry/deploy/lib/__init__.py +0 -0
  55. truefoundry/deploy/lib/auth/auth_service_client.py +81 -0
  56. truefoundry/deploy/lib/auth/credential_file_manager.py +115 -0
  57. truefoundry/deploy/lib/auth/credential_provider.py +131 -0
  58. truefoundry/deploy/lib/auth/servicefoundry_session.py +59 -0
  59. truefoundry/deploy/lib/clients/__init__.py +0 -0
  60. truefoundry/deploy/lib/clients/servicefoundry_client.py +723 -0
  61. truefoundry/deploy/lib/clients/shell_client.py +13 -0
  62. truefoundry/deploy/lib/clients/utils.py +41 -0
  63. truefoundry/deploy/lib/const.py +43 -0
  64. truefoundry/deploy/lib/dao/__init__.py +0 -0
  65. truefoundry/deploy/lib/dao/application.py +246 -0
  66. truefoundry/deploy/lib/dao/apply.py +80 -0
  67. truefoundry/deploy/lib/dao/version.py +33 -0
  68. truefoundry/deploy/lib/dao/workspace.py +71 -0
  69. truefoundry/deploy/lib/exceptions.py +23 -0
  70. truefoundry/deploy/lib/logs_utils.py +43 -0
  71. truefoundry/deploy/lib/messages.py +12 -0
  72. truefoundry/deploy/lib/model/__init__.py +0 -0
  73. truefoundry/deploy/lib/model/entity.py +382 -0
  74. truefoundry/deploy/lib/session.py +146 -0
  75. truefoundry/deploy/lib/util.py +70 -0
  76. truefoundry/deploy/lib/win32.py +129 -0
  77. truefoundry/deploy/v2/__init__.py +0 -0
  78. truefoundry/deploy/v2/lib/__init__.py +3 -0
  79. truefoundry/deploy/v2/lib/deploy.py +232 -0
  80. truefoundry/deploy/v2/lib/deployable_patched_models.py +72 -0
  81. truefoundry/deploy/v2/lib/models.py +53 -0
  82. truefoundry/deploy/v2/lib/patched_models.py +515 -0
  83. truefoundry/deploy/v2/lib/source.py +267 -0
  84. truefoundry/flyte/__init__.py +6 -0
  85. truefoundry/langchain/__init__.py +12 -1
  86. truefoundry/langchain/deprecated.py +302 -0
  87. truefoundry/langchain/truefoundry_chat.py +130 -0
  88. truefoundry/langchain/truefoundry_embeddings.py +171 -0
  89. truefoundry/langchain/truefoundry_llm.py +106 -0
  90. truefoundry/langchain/utils.py +85 -0
  91. truefoundry/logger.py +17 -0
  92. truefoundry/pydantic_v1.py +5 -0
  93. truefoundry/python_deploy_codegen.py +132 -0
  94. {truefoundry-0.2.10.dist-info → truefoundry-0.3.0rc2.dist-info}/METADATA +25 -6
  95. truefoundry-0.3.0rc2.dist-info/RECORD +125 -0
  96. truefoundry/deploy/cli/deploy.py +0 -165
  97. truefoundry-0.2.10.dist-info/RECORD +0 -38
  98. /truefoundry/{deploy/cli/version.py → version.py} +0 -0
  99. {truefoundry-0.2.10.dist-info → truefoundry-0.3.0rc2.dist-info}/WHEEL +0 -0
  100. {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