kubetorch 0.2.0__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 kubetorch might be problematic. Click here for more details.
- kubetorch/__init__.py +60 -0
- kubetorch/cli.py +1985 -0
- kubetorch/cli_utils.py +1025 -0
- kubetorch/config.py +453 -0
- kubetorch/constants.py +18 -0
- kubetorch/docs/Makefile +18 -0
- kubetorch/docs/__init__.py +0 -0
- kubetorch/docs/_ext/json_globaltoc.py +42 -0
- kubetorch/docs/api/cli.rst +10 -0
- kubetorch/docs/api/python/app.rst +21 -0
- kubetorch/docs/api/python/cls.rst +19 -0
- kubetorch/docs/api/python/compute.rst +25 -0
- kubetorch/docs/api/python/config.rst +11 -0
- kubetorch/docs/api/python/fn.rst +19 -0
- kubetorch/docs/api/python/image.rst +14 -0
- kubetorch/docs/api/python/secret.rst +18 -0
- kubetorch/docs/api/python/volumes.rst +13 -0
- kubetorch/docs/api/python.rst +101 -0
- kubetorch/docs/conf.py +69 -0
- kubetorch/docs/index.rst +20 -0
- kubetorch/docs/requirements.txt +5 -0
- kubetorch/globals.py +285 -0
- kubetorch/logger.py +59 -0
- kubetorch/resources/__init__.py +0 -0
- kubetorch/resources/callables/__init__.py +0 -0
- kubetorch/resources/callables/cls/__init__.py +0 -0
- kubetorch/resources/callables/cls/cls.py +157 -0
- kubetorch/resources/callables/fn/__init__.py +0 -0
- kubetorch/resources/callables/fn/fn.py +133 -0
- kubetorch/resources/callables/module.py +1416 -0
- kubetorch/resources/callables/utils.py +174 -0
- kubetorch/resources/compute/__init__.py +0 -0
- kubetorch/resources/compute/app.py +261 -0
- kubetorch/resources/compute/compute.py +2596 -0
- kubetorch/resources/compute/decorators.py +139 -0
- kubetorch/resources/compute/rbac.py +74 -0
- kubetorch/resources/compute/utils.py +1114 -0
- kubetorch/resources/compute/websocket.py +137 -0
- kubetorch/resources/images/__init__.py +1 -0
- kubetorch/resources/images/image.py +414 -0
- kubetorch/resources/images/images.py +74 -0
- kubetorch/resources/secrets/__init__.py +2 -0
- kubetorch/resources/secrets/kubernetes_secrets_client.py +412 -0
- kubetorch/resources/secrets/provider_secrets/__init__.py +0 -0
- kubetorch/resources/secrets/provider_secrets/anthropic_secret.py +12 -0
- kubetorch/resources/secrets/provider_secrets/aws_secret.py +16 -0
- kubetorch/resources/secrets/provider_secrets/azure_secret.py +14 -0
- kubetorch/resources/secrets/provider_secrets/cohere_secret.py +12 -0
- kubetorch/resources/secrets/provider_secrets/gcp_secret.py +16 -0
- kubetorch/resources/secrets/provider_secrets/github_secret.py +13 -0
- kubetorch/resources/secrets/provider_secrets/huggingface_secret.py +20 -0
- kubetorch/resources/secrets/provider_secrets/kubeconfig_secret.py +12 -0
- kubetorch/resources/secrets/provider_secrets/lambda_secret.py +13 -0
- kubetorch/resources/secrets/provider_secrets/langchain_secret.py +12 -0
- kubetorch/resources/secrets/provider_secrets/openai_secret.py +11 -0
- kubetorch/resources/secrets/provider_secrets/pinecone_secret.py +12 -0
- kubetorch/resources/secrets/provider_secrets/providers.py +93 -0
- kubetorch/resources/secrets/provider_secrets/ssh_secret.py +12 -0
- kubetorch/resources/secrets/provider_secrets/wandb_secret.py +11 -0
- kubetorch/resources/secrets/secret.py +238 -0
- kubetorch/resources/secrets/secret_factory.py +70 -0
- kubetorch/resources/secrets/utils.py +209 -0
- kubetorch/resources/volumes/__init__.py +0 -0
- kubetorch/resources/volumes/volume.py +365 -0
- kubetorch/servers/__init__.py +0 -0
- kubetorch/servers/http/__init__.py +0 -0
- kubetorch/servers/http/distributed_utils.py +3223 -0
- kubetorch/servers/http/http_client.py +730 -0
- kubetorch/servers/http/http_server.py +1788 -0
- kubetorch/servers/http/server_metrics.py +278 -0
- kubetorch/servers/http/utils.py +728 -0
- kubetorch/serving/__init__.py +0 -0
- kubetorch/serving/autoscaling.py +173 -0
- kubetorch/serving/base_service_manager.py +363 -0
- kubetorch/serving/constants.py +83 -0
- kubetorch/serving/deployment_service_manager.py +478 -0
- kubetorch/serving/knative_service_manager.py +519 -0
- kubetorch/serving/raycluster_service_manager.py +582 -0
- kubetorch/serving/service_manager.py +18 -0
- kubetorch/serving/templates/deployment_template.yaml +17 -0
- kubetorch/serving/templates/knative_service_template.yaml +19 -0
- kubetorch/serving/templates/kt_setup_template.sh.j2 +81 -0
- kubetorch/serving/templates/pod_template.yaml +194 -0
- kubetorch/serving/templates/raycluster_service_template.yaml +42 -0
- kubetorch/serving/templates/raycluster_template.yaml +35 -0
- kubetorch/serving/templates/service_template.yaml +21 -0
- kubetorch/serving/templates/workerset_template.yaml +36 -0
- kubetorch/serving/utils.py +377 -0
- kubetorch/utils.py +284 -0
- kubetorch-0.2.0.dist-info/METADATA +121 -0
- kubetorch-0.2.0.dist-info/RECORD +93 -0
- kubetorch-0.2.0.dist-info/WHEEL +4 -0
- kubetorch-0.2.0.dist-info/entry_points.txt +5 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from functools import update_wrapper
|
|
3
|
+
from typing import List, Union
|
|
4
|
+
|
|
5
|
+
from kubetorch.resources.callables.cls.cls import cls
|
|
6
|
+
from kubetorch.resources.callables.fn.fn import fn
|
|
7
|
+
from kubetorch.resources.compute.compute import Compute
|
|
8
|
+
|
|
9
|
+
# Helper class which allows us to chain decorators in a way that allows us to reverse the order of the decorators
|
|
10
|
+
# The `compute` decorator ultimately unwinds the calls to properly construct the Module.
|
|
11
|
+
class PartialModule:
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
fn_or_cls=None,
|
|
15
|
+
distribute_args=None,
|
|
16
|
+
autoscale_args=None,
|
|
17
|
+
async_=False,
|
|
18
|
+
):
|
|
19
|
+
self.fn_or_cls = fn_or_cls
|
|
20
|
+
self.distribute_args = distribute_args
|
|
21
|
+
self.autoscale_args = autoscale_args
|
|
22
|
+
self.async_ = async_
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# @kubetorch.compute decorator that the user can use to wrap a function they want to deploy to a cluster,
|
|
26
|
+
# and then deploy it with `kt deploy my_app.py` (we collect all the decorated functions imported in the file
|
|
27
|
+
# to deploy them).
|
|
28
|
+
def compute(
|
|
29
|
+
get_if_exists: bool = False, reload_prefixes: Union[str, List[str]] = [], **kwargs
|
|
30
|
+
):
|
|
31
|
+
def decorator(func_or_cls):
|
|
32
|
+
from kubetorch.globals import disable_decorators
|
|
33
|
+
|
|
34
|
+
if disable_decorators:
|
|
35
|
+
return func_or_cls
|
|
36
|
+
|
|
37
|
+
if isinstance(func_or_cls, PartialModule):
|
|
38
|
+
distribute_args = func_or_cls.distribute_args
|
|
39
|
+
autoscale_args = func_or_cls.autoscale_args
|
|
40
|
+
async_ = func_or_cls.async_
|
|
41
|
+
func_or_cls = func_or_cls.fn_or_cls
|
|
42
|
+
else:
|
|
43
|
+
distribute_args = None
|
|
44
|
+
autoscale_args = None
|
|
45
|
+
async_ = False
|
|
46
|
+
|
|
47
|
+
# If we're on the server attempting to load this function or class, just return it as is
|
|
48
|
+
if (
|
|
49
|
+
os.environ.get("KT_CLS_OR_FN_NAME") == func_or_cls.__name__
|
|
50
|
+
and os.environ.get("KT_MODULE_NAME") == func_or_cls.__module__
|
|
51
|
+
):
|
|
52
|
+
return func_or_cls
|
|
53
|
+
|
|
54
|
+
module_name = kwargs.pop("name", None)
|
|
55
|
+
|
|
56
|
+
if isinstance(func_or_cls, type):
|
|
57
|
+
new_module = cls(
|
|
58
|
+
func_or_cls,
|
|
59
|
+
name=module_name,
|
|
60
|
+
get_if_exists=get_if_exists,
|
|
61
|
+
reload_prefixes=reload_prefixes,
|
|
62
|
+
)
|
|
63
|
+
else:
|
|
64
|
+
new_module = fn(
|
|
65
|
+
func_or_cls,
|
|
66
|
+
name=module_name,
|
|
67
|
+
get_if_exists=get_if_exists,
|
|
68
|
+
reload_prefixes=reload_prefixes,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# All remaining kwargs are passed to the Compute constructor
|
|
72
|
+
new_module.compute = Compute(**kwargs)
|
|
73
|
+
new_module.compute.service_name = new_module.service_name
|
|
74
|
+
if distribute_args:
|
|
75
|
+
distribute_args, distribute_kwargs = distribute_args
|
|
76
|
+
new_module.compute.distribute(*distribute_args, **distribute_kwargs)
|
|
77
|
+
if autoscale_args:
|
|
78
|
+
autoscale_args, autoscale_kwargs = autoscale_args
|
|
79
|
+
new_module.compute.autoscale(*autoscale_args, **autoscale_kwargs)
|
|
80
|
+
if async_:
|
|
81
|
+
new_module.async_ = async_
|
|
82
|
+
|
|
83
|
+
# update_wrapper(new_module, func_or_cls)
|
|
84
|
+
return new_module
|
|
85
|
+
|
|
86
|
+
return decorator
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def async_(func_or_cls):
|
|
90
|
+
from kubetorch.globals import disable_decorators
|
|
91
|
+
|
|
92
|
+
if disable_decorators:
|
|
93
|
+
return func_or_cls
|
|
94
|
+
|
|
95
|
+
# If it's already a PartialModule (from other decorators), update it
|
|
96
|
+
if isinstance(func_or_cls, PartialModule):
|
|
97
|
+
func_or_cls.async_ = True
|
|
98
|
+
return func_or_cls
|
|
99
|
+
|
|
100
|
+
# Otherwise, create a new PartialModule
|
|
101
|
+
partial_module = PartialModule(fn_or_cls=func_or_cls, async_=True)
|
|
102
|
+
update_wrapper(partial_module, func_or_cls)
|
|
103
|
+
return partial_module
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def distribute(*args, **kwargs):
|
|
107
|
+
def decorator(func_or_cls):
|
|
108
|
+
from kubetorch.globals import disable_decorators
|
|
109
|
+
|
|
110
|
+
if disable_decorators:
|
|
111
|
+
return func_or_cls
|
|
112
|
+
|
|
113
|
+
# This is a partial so the order of decorator chaining can be reversed for best aesthetics
|
|
114
|
+
# the deploy method will actually call .distribute on the function or class after it's been deployed
|
|
115
|
+
partial_module = PartialModule(
|
|
116
|
+
fn_or_cls=func_or_cls, distribute_args=(args, kwargs)
|
|
117
|
+
)
|
|
118
|
+
update_wrapper(partial_module, func_or_cls)
|
|
119
|
+
return partial_module
|
|
120
|
+
|
|
121
|
+
return decorator
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def autoscale(*args, **kwargs):
|
|
125
|
+
def decorator(func_or_cls):
|
|
126
|
+
from kubetorch.globals import disable_decorators
|
|
127
|
+
|
|
128
|
+
if disable_decorators:
|
|
129
|
+
return func_or_cls
|
|
130
|
+
|
|
131
|
+
# This is a partial so the order of decorator chaining can be reversed for best aesthetics
|
|
132
|
+
# the deploy method will actually call .distribute on the function or class after it's been deployed
|
|
133
|
+
partial_module = PartialModule(
|
|
134
|
+
fn_or_cls=func_or_cls, autoscale_args=(args, kwargs)
|
|
135
|
+
)
|
|
136
|
+
update_wrapper(partial_module, func_or_cls)
|
|
137
|
+
return partial_module
|
|
138
|
+
|
|
139
|
+
return decorator
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from kubernetes import client, config
|
|
4
|
+
|
|
5
|
+
from kubetorch import globals
|
|
6
|
+
from kubetorch.logger import get_logger
|
|
7
|
+
|
|
8
|
+
from kubetorch.serving.constants import DEFAULT_SERVICE_ACCOUNT_NAME
|
|
9
|
+
|
|
10
|
+
logger = get_logger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def find_service_account_in_namespace(
|
|
14
|
+
namespace: str, service_account_name: str, core_v1: client.CoreV1Api
|
|
15
|
+
) -> Optional[client.V1ServiceAccount]:
|
|
16
|
+
"""Find a ServiceAccount in a given namespace."""
|
|
17
|
+
try:
|
|
18
|
+
return core_v1.read_namespaced_service_account(
|
|
19
|
+
name=service_account_name, namespace=namespace
|
|
20
|
+
)
|
|
21
|
+
except client.exceptions.ApiException as e:
|
|
22
|
+
if e.status != 404:
|
|
23
|
+
raise e
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def cleanup_namespace_and_service_account(namespace: str) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Cleanup a ServiceAccount and its associated ClusterRoleBindings in a given namespace.
|
|
30
|
+
"""
|
|
31
|
+
if namespace == globals.config.install_namespace:
|
|
32
|
+
raise ValueError(
|
|
33
|
+
f"Cannot cleanup ${globals.config.install_namespace} ServiceAccount"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Load kube config (works for both local and in-cluster)
|
|
37
|
+
try:
|
|
38
|
+
config.load_incluster_config()
|
|
39
|
+
except config.ConfigException:
|
|
40
|
+
config.load_kube_config()
|
|
41
|
+
|
|
42
|
+
core_v1 = client.CoreV1Api()
|
|
43
|
+
rbac_v1 = client.RbacAuthorizationV1Api()
|
|
44
|
+
|
|
45
|
+
service_account = find_service_account_in_namespace(
|
|
46
|
+
namespace, DEFAULT_SERVICE_ACCOUNT_NAME, core_v1
|
|
47
|
+
)
|
|
48
|
+
if not service_account:
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
# Delete the ServiceAccount
|
|
52
|
+
core_v1.delete_namespaced_service_account(
|
|
53
|
+
name=DEFAULT_SERVICE_ACCOUNT_NAME, namespace=namespace
|
|
54
|
+
)
|
|
55
|
+
logger.info(f"Deleted ServiceAccount {namespace}/{DEFAULT_SERVICE_ACCOUNT_NAME}")
|
|
56
|
+
|
|
57
|
+
# Delete all ClusterRoleBindings that reference the ServiceAccount
|
|
58
|
+
bindings = rbac_v1.list_namespaced_role_binding(
|
|
59
|
+
namespace=namespace,
|
|
60
|
+
label_selector=f"kubetorch.com/service-account={DEFAULT_SERVICE_ACCOUNT_NAME},kubetorch.com/namespace={namespace}",
|
|
61
|
+
)
|
|
62
|
+
for binding in bindings.items:
|
|
63
|
+
rbac_v1.delete_namespaced_role_binding(
|
|
64
|
+
name=binding.metadata.name, namespace=namespace
|
|
65
|
+
)
|
|
66
|
+
logger.info(f"Deleted RoleBinding {binding.metadata.name}")
|
|
67
|
+
|
|
68
|
+
logger.info(
|
|
69
|
+
f"Cleanup completed for ServiceAccount {namespace}/{DEFAULT_SERVICE_ACCOUNT_NAME}"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Delete the namespace
|
|
73
|
+
core_v1.delete_namespace(name=namespace)
|
|
74
|
+
logger.info(f"Deleted namespace {namespace}")
|