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.

Files changed (93) hide show
  1. kubetorch/__init__.py +60 -0
  2. kubetorch/cli.py +1985 -0
  3. kubetorch/cli_utils.py +1025 -0
  4. kubetorch/config.py +453 -0
  5. kubetorch/constants.py +18 -0
  6. kubetorch/docs/Makefile +18 -0
  7. kubetorch/docs/__init__.py +0 -0
  8. kubetorch/docs/_ext/json_globaltoc.py +42 -0
  9. kubetorch/docs/api/cli.rst +10 -0
  10. kubetorch/docs/api/python/app.rst +21 -0
  11. kubetorch/docs/api/python/cls.rst +19 -0
  12. kubetorch/docs/api/python/compute.rst +25 -0
  13. kubetorch/docs/api/python/config.rst +11 -0
  14. kubetorch/docs/api/python/fn.rst +19 -0
  15. kubetorch/docs/api/python/image.rst +14 -0
  16. kubetorch/docs/api/python/secret.rst +18 -0
  17. kubetorch/docs/api/python/volumes.rst +13 -0
  18. kubetorch/docs/api/python.rst +101 -0
  19. kubetorch/docs/conf.py +69 -0
  20. kubetorch/docs/index.rst +20 -0
  21. kubetorch/docs/requirements.txt +5 -0
  22. kubetorch/globals.py +285 -0
  23. kubetorch/logger.py +59 -0
  24. kubetorch/resources/__init__.py +0 -0
  25. kubetorch/resources/callables/__init__.py +0 -0
  26. kubetorch/resources/callables/cls/__init__.py +0 -0
  27. kubetorch/resources/callables/cls/cls.py +157 -0
  28. kubetorch/resources/callables/fn/__init__.py +0 -0
  29. kubetorch/resources/callables/fn/fn.py +133 -0
  30. kubetorch/resources/callables/module.py +1416 -0
  31. kubetorch/resources/callables/utils.py +174 -0
  32. kubetorch/resources/compute/__init__.py +0 -0
  33. kubetorch/resources/compute/app.py +261 -0
  34. kubetorch/resources/compute/compute.py +2596 -0
  35. kubetorch/resources/compute/decorators.py +139 -0
  36. kubetorch/resources/compute/rbac.py +74 -0
  37. kubetorch/resources/compute/utils.py +1114 -0
  38. kubetorch/resources/compute/websocket.py +137 -0
  39. kubetorch/resources/images/__init__.py +1 -0
  40. kubetorch/resources/images/image.py +414 -0
  41. kubetorch/resources/images/images.py +74 -0
  42. kubetorch/resources/secrets/__init__.py +2 -0
  43. kubetorch/resources/secrets/kubernetes_secrets_client.py +412 -0
  44. kubetorch/resources/secrets/provider_secrets/__init__.py +0 -0
  45. kubetorch/resources/secrets/provider_secrets/anthropic_secret.py +12 -0
  46. kubetorch/resources/secrets/provider_secrets/aws_secret.py +16 -0
  47. kubetorch/resources/secrets/provider_secrets/azure_secret.py +14 -0
  48. kubetorch/resources/secrets/provider_secrets/cohere_secret.py +12 -0
  49. kubetorch/resources/secrets/provider_secrets/gcp_secret.py +16 -0
  50. kubetorch/resources/secrets/provider_secrets/github_secret.py +13 -0
  51. kubetorch/resources/secrets/provider_secrets/huggingface_secret.py +20 -0
  52. kubetorch/resources/secrets/provider_secrets/kubeconfig_secret.py +12 -0
  53. kubetorch/resources/secrets/provider_secrets/lambda_secret.py +13 -0
  54. kubetorch/resources/secrets/provider_secrets/langchain_secret.py +12 -0
  55. kubetorch/resources/secrets/provider_secrets/openai_secret.py +11 -0
  56. kubetorch/resources/secrets/provider_secrets/pinecone_secret.py +12 -0
  57. kubetorch/resources/secrets/provider_secrets/providers.py +93 -0
  58. kubetorch/resources/secrets/provider_secrets/ssh_secret.py +12 -0
  59. kubetorch/resources/secrets/provider_secrets/wandb_secret.py +11 -0
  60. kubetorch/resources/secrets/secret.py +238 -0
  61. kubetorch/resources/secrets/secret_factory.py +70 -0
  62. kubetorch/resources/secrets/utils.py +209 -0
  63. kubetorch/resources/volumes/__init__.py +0 -0
  64. kubetorch/resources/volumes/volume.py +365 -0
  65. kubetorch/servers/__init__.py +0 -0
  66. kubetorch/servers/http/__init__.py +0 -0
  67. kubetorch/servers/http/distributed_utils.py +3223 -0
  68. kubetorch/servers/http/http_client.py +730 -0
  69. kubetorch/servers/http/http_server.py +1788 -0
  70. kubetorch/servers/http/server_metrics.py +278 -0
  71. kubetorch/servers/http/utils.py +728 -0
  72. kubetorch/serving/__init__.py +0 -0
  73. kubetorch/serving/autoscaling.py +173 -0
  74. kubetorch/serving/base_service_manager.py +363 -0
  75. kubetorch/serving/constants.py +83 -0
  76. kubetorch/serving/deployment_service_manager.py +478 -0
  77. kubetorch/serving/knative_service_manager.py +519 -0
  78. kubetorch/serving/raycluster_service_manager.py +582 -0
  79. kubetorch/serving/service_manager.py +18 -0
  80. kubetorch/serving/templates/deployment_template.yaml +17 -0
  81. kubetorch/serving/templates/knative_service_template.yaml +19 -0
  82. kubetorch/serving/templates/kt_setup_template.sh.j2 +81 -0
  83. kubetorch/serving/templates/pod_template.yaml +194 -0
  84. kubetorch/serving/templates/raycluster_service_template.yaml +42 -0
  85. kubetorch/serving/templates/raycluster_template.yaml +35 -0
  86. kubetorch/serving/templates/service_template.yaml +21 -0
  87. kubetorch/serving/templates/workerset_template.yaml +36 -0
  88. kubetorch/serving/utils.py +377 -0
  89. kubetorch/utils.py +284 -0
  90. kubetorch-0.2.0.dist-info/METADATA +121 -0
  91. kubetorch-0.2.0.dist-info/RECORD +93 -0
  92. kubetorch-0.2.0.dist-info/WHEEL +4 -0
  93. 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}")