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,129 @@
1
+ """
2
+ Win32 compatibility utilities.
3
+ https://github.com/zeromq/pyzmq/blob/3e7e83a841829fcb46b7e1a881d968fb5471ef62/zmq/utils/win32.py
4
+ """
5
+
6
+ # -----------------------------------------------------------------------------
7
+ # Copyright (C) PyZMQ Developers
8
+ # Distributed under the terms of the Modified BSD License.
9
+ # -----------------------------------------------------------------------------
10
+
11
+ import os
12
+ from typing import Any, Callable, Optional
13
+
14
+
15
+ class allow_interrupt:
16
+ """Utility for fixing CTRL-C events on Windows.
17
+
18
+ On Windows, the Python interpreter intercepts CTRL-C events in order to
19
+ translate them into ``KeyboardInterrupt`` exceptions. It (presumably)
20
+ does this by setting a flag in its "console control handler" and
21
+ checking it later at a convenient location in the interpreter.
22
+
23
+ However, when the Python interpreter is blocked waiting for the ZMQ
24
+ poll operation to complete, it must wait for ZMQ's ``select()``
25
+ operation to complete before translating the CTRL-C event into the
26
+ ``KeyboardInterrupt`` exception.
27
+
28
+ The only way to fix this seems to be to add our own "console control
29
+ handler" and perform some application-defined operation that will
30
+ unblock the ZMQ polling operation in order to force ZMQ to pass control
31
+ back to the Python interpreter.
32
+
33
+ This context manager performs all that Windows-y stuff, providing you
34
+ with a hook that is called when a CTRL-C event is intercepted. This
35
+ hook allows you to unblock your ZMQ poll operation immediately, which
36
+ will then result in the expected ``KeyboardInterrupt`` exception.
37
+
38
+ Without this context manager, your ZMQ-based application will not
39
+ respond normally to CTRL-C events on Windows. If a CTRL-C event occurs
40
+ while blocked on ZMQ socket polling, the translation to a
41
+ ``KeyboardInterrupt`` exception will be delayed until the I/O completes
42
+ and control returns to the Python interpreter (this may never happen if
43
+ you use an infinite timeout).
44
+
45
+ A no-op implementation is provided on non-Win32 systems to avoid the
46
+ application from having to conditionally use it.
47
+
48
+ Example usage:
49
+
50
+ .. sourcecode:: python
51
+
52
+ def stop_my_application():
53
+ # ...
54
+
55
+ with allow_interrupt(stop_my_application):
56
+ # main polling loop.
57
+
58
+ In a typical ZMQ application, you would use the "self pipe trick" to
59
+ send message to a ``PAIR`` socket in order to interrupt your blocking
60
+ socket polling operation.
61
+
62
+ In a Tornado event loop, you can use the ``IOLoop.stop`` method to
63
+ unblock your I/O loop.
64
+ """
65
+
66
+ def __init__(self, action: Optional[Callable[[], Any]] = None) -> None:
67
+ """Translate ``action`` into a CTRL-C handler.
68
+
69
+ ``action`` is a callable that takes no arguments and returns no
70
+ value (returned value is ignored). It must *NEVER* raise an
71
+ exception.
72
+
73
+ If unspecified, a no-op will be used.
74
+ """
75
+ if os.name != "nt":
76
+ return
77
+ self._init_action(action)
78
+
79
+ def _init_action(self, action):
80
+ from ctypes import WINFUNCTYPE, windll
81
+ from ctypes.wintypes import BOOL, DWORD
82
+
83
+ kernel32 = windll.LoadLibrary("kernel32")
84
+
85
+ # <http://msdn.microsoft.com/en-us/library/ms686016.aspx>
86
+ PHANDLER_ROUTINE = WINFUNCTYPE(BOOL, DWORD)
87
+ SetConsoleCtrlHandler = self._SetConsoleCtrlHandler = (
88
+ kernel32.SetConsoleCtrlHandler
89
+ )
90
+ SetConsoleCtrlHandler.argtypes = (PHANDLER_ROUTINE, BOOL)
91
+ SetConsoleCtrlHandler.restype = BOOL
92
+
93
+ if action is None:
94
+ action = lambda: None # noqa: E731
95
+ self.action = action
96
+
97
+ @PHANDLER_ROUTINE
98
+ def handle(event):
99
+ if event == 0: # CTRL_C_EVENT
100
+ action()
101
+ # Typical C implementations would return 1 to indicate that
102
+ # the event was processed and other control handlers in the
103
+ # stack should not be executed. However, that would
104
+ # prevent the Python interpreter's handler from translating
105
+ # CTRL-C to a `KeyboardInterrupt` exception, so we pretend
106
+ # that we didn't handle it.
107
+ return 0
108
+
109
+ self.handle = handle
110
+
111
+ def __enter__(self):
112
+ """Install the custom CTRL-C handler."""
113
+ if os.name != "nt":
114
+ return
115
+ result = self._SetConsoleCtrlHandler(self.handle, 1)
116
+ if result == 0:
117
+ # Have standard library automatically call `GetLastError()` and
118
+ # `FormatMessage()` into a nice exception object :-)
119
+ raise OSError()
120
+
121
+ def __exit__(self, *args):
122
+ """Remove the custom CTRL-C handler."""
123
+ if os.name != "nt":
124
+ return
125
+ result = self._SetConsoleCtrlHandler(self.handle, 0)
126
+ if result == 0:
127
+ # Have standard library automatically call `GetLastError()` and
128
+ # `FormatMessage()` into a nice exception object :-)
129
+ raise OSError()
File without changes
@@ -0,0 +1,3 @@
1
+ # NOTE: Later all of these can be under a `models` or some other module
2
+ # I am not entirely sure about the structure of `lib` module yet
3
+ # This can go through another round of refactoring
@@ -0,0 +1,232 @@
1
+ import sys
2
+ import time
3
+ from typing import List, Optional, TypeVar
4
+
5
+ from rich.status import Status
6
+
7
+ from truefoundry.deploy.auto_gen import models as auto_gen_models
8
+ from truefoundry.deploy.builder.docker_service import env_has_docker
9
+ from truefoundry.deploy.lib.clients.servicefoundry_client import (
10
+ ServiceFoundryServiceClient,
11
+ )
12
+ from truefoundry.deploy.lib.clients.utils import poll_for_function
13
+ from truefoundry.deploy.lib.dao.workspace import get_workspace_by_fqn
14
+ from truefoundry.deploy.lib.model.entity import Deployment, DeploymentTransitionStatus
15
+ from truefoundry.deploy.lib.util import get_application_fqn_from_deployment_fqn
16
+ from truefoundry.deploy.v2.lib.models import BuildResponse
17
+ from truefoundry.deploy.v2.lib.source import (
18
+ local_source_to_image,
19
+ local_source_to_remote_source,
20
+ )
21
+ from truefoundry.logger import logger
22
+ from truefoundry.pydantic_v1 import BaseModel
23
+
24
+ Component = TypeVar("Component", bound=BaseModel)
25
+
26
+
27
+ def _handle_if_local_source(component: Component, workspace_fqn: str) -> Component:
28
+ if (
29
+ hasattr(component, "image")
30
+ and isinstance(component.image, auto_gen_models.Build)
31
+ and isinstance(component.image.build_source, auto_gen_models.LocalSource)
32
+ ):
33
+ new_component = component.copy(deep=True)
34
+
35
+ if component.image.build_source.local_build:
36
+ if not env_has_docker():
37
+ logger.warning(
38
+ "Did not find Docker locally installed on this system, image will be built remotely. "
39
+ "For faster builds it is recommended to install Docker locally. "
40
+ "If you always want to build remotely, "
41
+ "please set `image.build_source.local_build` to `false` in your YAML spec or equivalently set "
42
+ "`image=Build(build_source=LocalSource(local_build=False, ...))` in your "
43
+ "`Service` or `Job` definition code."
44
+ )
45
+ local_build = False
46
+ else:
47
+ logger.info(
48
+ "Found locally installed docker, image will be built locally and then pushed. "
49
+ "If you want to always build remotely instead of locally, "
50
+ "please set `image.build_source.local_build` to `false` in your YAML spec or equivalently set "
51
+ "`image=Build(build_source=LocalSource(local_build=False, ...))` in your "
52
+ "`Service` or `Job` definition code."
53
+ )
54
+ local_build = True
55
+ else:
56
+ logger.info(
57
+ "Image will be built remotely because `image.build_source.local_build` is set to `false`. "
58
+ "For faster builds it is recommended to install Docker locally and "
59
+ "set `image.build_source.local_build` to `true` in your YAML spec "
60
+ "or equivalently set `image=Build(build_source=LocalSource(local_build=True, ...))` "
61
+ "in your `Service` or `Job` definition code."
62
+ )
63
+ local_build = False
64
+
65
+ if local_build:
66
+ # We are to build the image locally, push and update `image` in spec
67
+ logger.info("Building image for %s '%s'", component.type, component.name)
68
+ new_component.image = local_source_to_image(
69
+ build=component.image,
70
+ docker_registry_fqn=component.image.docker_registry,
71
+ workspace_fqn=workspace_fqn,
72
+ component_name=component.name,
73
+ )
74
+ else:
75
+ # We'll build image on Truefoundry servers, upload the source and update image.build_source
76
+ logger.info("Uploading code for %s '%s'", component.type, component.name)
77
+ new_component.image.build_source = local_source_to_remote_source(
78
+ local_source=component.image.build_source,
79
+ workspace_fqn=workspace_fqn,
80
+ component_name=component.name,
81
+ )
82
+ logger.debug("Uploaded code for %s '%s'", component.type, component.name)
83
+ return new_component
84
+ return component
85
+
86
+
87
+ def _log_application_dashboard_url(deployment: Deployment, log_message: str):
88
+ application_id = deployment.applicationId
89
+
90
+ # TODO: is there any simpler way to get this? :cry
91
+ client = ServiceFoundryServiceClient()
92
+
93
+ url = f"{client.base_url.strip('/')}/applications/{application_id}?tab=deployments"
94
+ logger.info(log_message, url)
95
+
96
+
97
+ def _tail_build_logs(build_responses: List[BuildResponse]) -> None:
98
+ client = ServiceFoundryServiceClient()
99
+
100
+ # TODO: Explore other options like,
101
+ # https://rich.readthedocs.io/en/stable/live.html#live-display
102
+ # How does docker/compose does multiple build logs?
103
+ for build_response in build_responses:
104
+ logger.info("Tailing build logs for '%s'", build_response.componentName)
105
+ client.tail_build_logs(build_response=build_response, wait=True)
106
+
107
+
108
+ def _deploy_wait_handler(
109
+ deployment: Deployment,
110
+ ) -> Optional[DeploymentTransitionStatus]:
111
+ _log_application_dashboard_url(
112
+ deployment=deployment,
113
+ log_message=(
114
+ "You can track the progress below or on the dashboard:- '%s'\n"
115
+ "You can press Ctrl + C to exit the tailing of build logs "
116
+ "and deployment will continue on the server"
117
+ ),
118
+ )
119
+ with Status(status="Polling for deployment status") as spinner:
120
+ last_status_printed = None
121
+ client = ServiceFoundryServiceClient()
122
+ start_time = time.monotonic()
123
+ total_timeout_time: int = 300
124
+ poll_interval_seconds = 5
125
+ time_elapsed = 0
126
+
127
+ for deployment_statuses in poll_for_function(
128
+ client.get_deployment_statuses,
129
+ poll_after_secs=poll_interval_seconds,
130
+ application_id=deployment.applicationId,
131
+ deployment_id=deployment.id,
132
+ ):
133
+ if len(deployment_statuses) == 0:
134
+ logger.warning("Did not receive any deployment status")
135
+ continue
136
+
137
+ latest_deployment_status = deployment_statuses[-1]
138
+
139
+ status_to_print = (
140
+ latest_deployment_status.transition or latest_deployment_status.status
141
+ )
142
+ spinner.update(status=f"Current state: {status_to_print}")
143
+ if status_to_print != last_status_printed:
144
+ if DeploymentTransitionStatus.is_failure_state(status_to_print):
145
+ logger.error("State: %r", status_to_print)
146
+ else:
147
+ logger.info("State: %r", status_to_print)
148
+ last_status_printed = status_to_print
149
+
150
+ if latest_deployment_status.state.isTerminalState:
151
+ break
152
+
153
+ if (
154
+ latest_deployment_status.transition
155
+ == DeploymentTransitionStatus.BUILDING
156
+ ):
157
+ build_responses = client.get_deployment_build_response(
158
+ application_id=deployment.applicationId, deployment_id=deployment.id
159
+ )
160
+ _tail_build_logs(build_responses)
161
+
162
+ time_elapsed = time.monotonic() - start_time
163
+ if time_elapsed > total_timeout_time:
164
+ logger.warning("Polled server for %s secs.", int(time_elapsed))
165
+ break
166
+
167
+ return last_status_printed
168
+
169
+
170
+ def _warn_when_gpu_selected_without_cuda(component: Component):
171
+ is_python_build_without_cuda = (
172
+ hasattr(component, "image")
173
+ and isinstance(component.image, auto_gen_models.Build)
174
+ and isinstance(component.image.build_spec, auto_gen_models.PythonBuild)
175
+ and not component.image.build_spec.cuda_version
176
+ )
177
+ uses_gpu = (
178
+ hasattr(component, "resources")
179
+ and isinstance(component, auto_gen_models.Resources)
180
+ and component.resources.gpu_count > 0
181
+ )
182
+ if is_python_build_without_cuda and uses_gpu:
183
+ logger.warning(
184
+ "Warning: `gpu_count` is greater than 0 in `Resources` (i.e. `resources.gpu_count`) "
185
+ "but no `cuda_version` was passed to `PythonBuild` "
186
+ "(i.e. `image.build_spec.cuda_version`). "
187
+ "Your application might optionally need CUDA toolkit installed "
188
+ "to utilize the GPU. You can choose one by passing one of "
189
+ "`truefoundry.deploy.CUDAVersion` in `PythonBuild` instance. "
190
+ "\n\nE.g.\n```\nPythonBuild(..., cuda_version=CUDAVersion.CUDA_11_3_CUDNN8)\n```"
191
+ )
192
+
193
+
194
+ def deploy_component(
195
+ component: Component, workspace_fqn: str, wait: bool = True
196
+ ) -> Deployment:
197
+ _warn_when_gpu_selected_without_cuda(component=component)
198
+ workspace_id = get_workspace_by_fqn(workspace_fqn).id
199
+ updated_component = _handle_if_local_source(
200
+ component=component, workspace_fqn=workspace_fqn
201
+ )
202
+ client = ServiceFoundryServiceClient()
203
+ response = client.deploy_application(
204
+ workspace_id=workspace_id, application=updated_component
205
+ )
206
+ logger.info(
207
+ "🚀 Deployment started for application '%s'. Deployment FQN is '%s'.",
208
+ updated_component.name,
209
+ response.fqn,
210
+ )
211
+ if wait:
212
+ try:
213
+ last_status_printed = _deploy_wait_handler(deployment=response)
214
+ if not last_status_printed or DeploymentTransitionStatus.is_failure_state(
215
+ last_status_printed
216
+ ):
217
+ deployment_tab_url = f"{client.base_url.strip('/')}/applications/{response.applicationId}?tab=deployments"
218
+ message = f"Deployment Failed. Please refer to the logs for additional details - {deployment_tab_url}"
219
+ sys.exit(message)
220
+ except KeyboardInterrupt:
221
+ logger.info("Ctrl-c executed. The deployment will still continue.")
222
+
223
+ deployment_fqn = response.fqn
224
+ application_fqn = get_application_fqn_from_deployment_fqn(deployment_fqn)
225
+ logger.info("Deployment FQN: %s", deployment_fqn)
226
+ logger.info("Application FQN: %s", application_fqn)
227
+
228
+ _log_application_dashboard_url(
229
+ deployment=response,
230
+ log_message="You can find the application on the dashboard:- '%s'",
231
+ )
232
+ return response
@@ -0,0 +1,72 @@
1
+ from typing import Literal, Union
2
+
3
+ from truefoundry.deploy.auto_gen import models
4
+ from truefoundry.deploy.lib.model.entity import Deployment
5
+ from truefoundry.deploy.v2.lib.deploy import deploy_component
6
+ from truefoundry.pydantic_v1 import BaseModel, Field, conint
7
+
8
+
9
+ class DeployablePatchedModelBase(BaseModel):
10
+ class Config:
11
+ extra = "forbid"
12
+
13
+ def deploy(self, workspace_fqn: str, wait: bool = True) -> Deployment:
14
+ return deploy_component(component=self, workspace_fqn=workspace_fqn, wait=wait)
15
+
16
+
17
+ class Service(models.Service, DeployablePatchedModelBase):
18
+ type: Literal["service"] = "service"
19
+ resources: models.Resources = Field(default_factory=models.Resources)
20
+ # This is being patched because cue export marks this as a "number"
21
+ replicas: Union[conint(ge=0, le=100), models.ServiceAutoscaling] = Field(
22
+ 1,
23
+ description="+label=Replicas\n+usage=Replicas of service you want to run\n+icon=fa-clone\n+sort=3",
24
+ )
25
+
26
+
27
+ class Job(models.Job, DeployablePatchedModelBase):
28
+ type: Literal["job"] = "job"
29
+ resources: models.Resources = Field(default_factory=models.Resources)
30
+
31
+
32
+ class Notebook(models.Notebook, DeployablePatchedModelBase):
33
+ type: Literal["notebook"] = "notebook"
34
+ resources: models.Resources = Field(default_factory=models.Resources)
35
+
36
+
37
+ class Codeserver(models.Codeserver, DeployablePatchedModelBase):
38
+ type: Literal["codeserver"] = "codeserver"
39
+
40
+
41
+ class Helm(models.Helm, DeployablePatchedModelBase):
42
+ type: Literal["helm"] = "helm"
43
+
44
+
45
+ class Volume(models.Volume, DeployablePatchedModelBase):
46
+ type: Literal["volume"] = "volume"
47
+
48
+
49
+ class ApplicationSet(models.ApplicationSet, DeployablePatchedModelBase):
50
+ type: Literal["application-set"] = "application-set"
51
+
52
+
53
+ class AsyncService(models.AsyncService, DeployablePatchedModelBase):
54
+ type: Literal["async-service"] = "async-service"
55
+ replicas: Union[conint(ge=0, le=100), models.AsyncServiceAutoscaling] = 1
56
+ resources: models.Resources = Field(default_factory=models.Resources)
57
+
58
+
59
+ class SSHServer(models.SSHServer, DeployablePatchedModelBase):
60
+ type: Literal["ssh-server"] = "ssh-server"
61
+ resources: models.Resources = Field(default_factory=models.Resources)
62
+
63
+
64
+ class Application(models.Application, DeployablePatchedModelBase):
65
+ def deploy(self, workspace_fqn: str, wait: bool = True) -> Deployment:
66
+ return deploy_component(
67
+ component=self.__root__, workspace_fqn=workspace_fqn, wait=wait
68
+ )
69
+
70
+
71
+ class Workflow(models.Workflow, DeployablePatchedModelBase):
72
+ type: Literal["workflow"] = "workflow"
@@ -0,0 +1,53 @@
1
+ import datetime
2
+ from typing import List, Optional
3
+
4
+ from truefoundry.pydantic_v1 import BaseModel, Extra, create_model
5
+
6
+
7
+ class BuildResponse(BaseModel):
8
+ id: str
9
+ name: str
10
+ # TODO: make status an enum
11
+ status: str
12
+ # TODO: should we just make these fields
13
+ # snake-case and add camelCase aliases?
14
+ deploymentId: str
15
+ componentName: str
16
+ createdAt: datetime.datetime
17
+ updatedAt: datetime.datetime
18
+ imageUri: Optional[str]
19
+ failureReason: Optional[str]
20
+ getLogsUrl: str
21
+ tailLogsUrl: str
22
+ logsStartTs: int
23
+
24
+ class Config:
25
+ extra = Extra.allow
26
+
27
+
28
+ class AppDeploymentStatusResponse(BaseModel):
29
+ state: create_model(
30
+ "State",
31
+ isTerminalState=(bool, ...),
32
+ type=(str, ...),
33
+ transitions=(List[str], ...),
34
+ )
35
+
36
+ id: str
37
+ status: str
38
+ message: Optional[str]
39
+ transition: Optional[str]
40
+
41
+ class Config:
42
+ extra = Extra.allow
43
+
44
+
45
+ class DeploymentFqnResponse(BaseModel):
46
+ deploymentId: str
47
+ applicationId: str
48
+ workspaceId: str
49
+
50
+
51
+ class ApplicationFqnResponse(BaseModel):
52
+ applicationId: str
53
+ workspaceId: str