indexify 0.3.1__py3-none-any.whl → 0.3.3__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.
- indexify/cli/cli.py +70 -8
- indexify/executor/api_objects.py +1 -1
- indexify/function_executor/service.py +19 -15
- {indexify-0.3.1.dist-info → indexify-0.3.3.dist-info}/METADATA +1 -1
- {indexify-0.3.1.dist-info → indexify-0.3.3.dist-info}/RECORD +7 -7
- {indexify-0.3.1.dist-info → indexify-0.3.3.dist-info}/WHEEL +0 -0
- {indexify-0.3.1.dist-info → indexify-0.3.3.dist-info}/entry_points.txt +0 -0
indexify/cli/cli.py
CHANGED
@@ -6,6 +6,8 @@ from indexify.utils.logging import (
|
|
6
6
|
|
7
7
|
configure_logging_early()
|
8
8
|
|
9
|
+
import importlib.metadata
|
10
|
+
import json
|
9
11
|
import os
|
10
12
|
import shutil
|
11
13
|
import signal
|
@@ -17,6 +19,7 @@ from importlib.metadata import version
|
|
17
19
|
from pathlib import Path
|
18
20
|
from typing import Annotated, List, Optional, Tuple
|
19
21
|
|
22
|
+
import docker
|
20
23
|
import nanoid
|
21
24
|
import structlog
|
22
25
|
import typer
|
@@ -190,7 +193,9 @@ def executor(
|
|
190
193
|
"--function",
|
191
194
|
"-f",
|
192
195
|
help="Function that the executor will run "
|
193
|
-
"specified as <namespace>:<workflow>:<function>:<version>"
|
196
|
+
"specified as <namespace>:<workflow>:<function>:<version>"
|
197
|
+
"version is optional, not specifying it will make the server send any version"
|
198
|
+
"of the function",
|
194
199
|
),
|
195
200
|
] = None,
|
196
201
|
config_path: Optional[str] = typer.Option(
|
@@ -261,16 +266,23 @@ def _parse_function_uris(uri_strs: Optional[List[str]]) -> Optional[List[Functio
|
|
261
266
|
uris: List[FunctionURI] = []
|
262
267
|
for uri_str in uri_strs:
|
263
268
|
tokens = uri_str.split(":")
|
264
|
-
|
269
|
+
# FIXME bring this back when we have a dynamic scheduler
|
270
|
+
# if len(tokens) != 4:
|
271
|
+
if len(tokens) < 3 and len(tokens) > 4:
|
265
272
|
raise typer.BadParameter(
|
266
|
-
"Function should be specified as <namespace>:<workflow>:<function>:<version>"
|
273
|
+
"Function should be specified as <namespace>:<workflow>:<function>:<version> or"
|
274
|
+
"<namespace>:<workflow>:<function>"
|
267
275
|
)
|
276
|
+
try:
|
277
|
+
version = tokens[3]
|
278
|
+
except IndexError:
|
279
|
+
version = None
|
268
280
|
uris.append(
|
269
281
|
FunctionURI(
|
270
282
|
namespace=tokens[0],
|
271
283
|
compute_graph=tokens[1],
|
272
284
|
compute_fn=tokens[2],
|
273
|
-
version=
|
285
|
+
version=version,
|
274
286
|
)
|
275
287
|
)
|
276
288
|
return uris
|
@@ -285,7 +297,57 @@ def _create_image(image: Image, python_sdk_path):
|
|
285
297
|
|
286
298
|
|
287
299
|
def _build_image(image: Image, python_sdk_path: Optional[str] = None):
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
300
|
+
docker_file = _generate_dockerfile(image, python_sdk_path=python_sdk_path)
|
301
|
+
image_name = f"{image._image_name}:{image._tag}"
|
302
|
+
|
303
|
+
# low_level_client = docker.APIClient(base_url=docker_client.api.base_url)
|
304
|
+
docker_host = os.getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
|
305
|
+
low_level_client = docker.APIClient(base_url=docker_host)
|
306
|
+
docker.api.build.process_dockerfile = lambda dockerfile, path: (
|
307
|
+
"Dockerfile",
|
308
|
+
dockerfile,
|
309
|
+
)
|
310
|
+
generator = low_level_client.build(
|
311
|
+
dockerfile=docker_file,
|
312
|
+
rm=True,
|
313
|
+
path=".",
|
314
|
+
tag=image_name,
|
315
|
+
)
|
316
|
+
|
317
|
+
for output in generator:
|
318
|
+
for line in output.decode().splitlines():
|
319
|
+
json_line = json.loads(line)
|
320
|
+
if "stream" in json_line:
|
321
|
+
print(json_line["stream"], end="")
|
322
|
+
|
323
|
+
elif "errorDetail" in json_line:
|
324
|
+
print(json_line["errorDetail"]["message"])
|
325
|
+
|
326
|
+
|
327
|
+
def _generate_dockerfile(image, python_sdk_path: Optional[str] = None):
|
328
|
+
docker_contents = [
|
329
|
+
f"FROM {image._base_image}",
|
330
|
+
"RUN mkdir -p ~/.indexify",
|
331
|
+
f"RUN echo {image._image_name} > ~/.indexify/image_name", # TODO: Do we still use this in executors?
|
332
|
+
f"RUN echo {image.hash()} > ~/.indexify/image_hash", # TODO: Do we still use this in executors?
|
333
|
+
"WORKDIR /app",
|
334
|
+
]
|
335
|
+
|
336
|
+
for build_op in image._build_ops:
|
337
|
+
docker_contents.append(build_op.render())
|
338
|
+
|
339
|
+
if python_sdk_path is not None:
|
340
|
+
print(f"Building image {image._image_name} with local version of the SDK")
|
341
|
+
|
342
|
+
if not os.path.exists(python_sdk_path):
|
343
|
+
print(f"error: {python_sdk_path} does not exist")
|
344
|
+
os.exit(1)
|
345
|
+
docker_contents.append(f"COPY {python_sdk_path} /app/python-sdk")
|
346
|
+
docker_contents.append("RUN (cd /app/python-sdk && pip install .)")
|
347
|
+
else:
|
348
|
+
docker_contents.append(
|
349
|
+
f"RUN pip install indexify=={importlib.metadata.version('indexify')}"
|
350
|
+
)
|
351
|
+
|
352
|
+
docker_file = "\n".join(docker_contents)
|
353
|
+
return docker_file
|
indexify/executor/api_objects.py
CHANGED
@@ -86,33 +86,37 @@ class Service(FunctionExecutorServicer):
|
|
86
86
|
# If our code raises an exception the grpc framework converts it into GRPC_STATUS_UNKNOWN
|
87
87
|
# error with the exception message. Differentiating errors is not needed for now.
|
88
88
|
RunTaskRequestValidator(request=request).check()
|
89
|
+
self._check_task_routed_correctly(request)
|
89
90
|
|
91
|
+
return RunTaskHandler(
|
92
|
+
request=request,
|
93
|
+
graph_name=self._graph_name,
|
94
|
+
graph_version=self._graph_version,
|
95
|
+
function_name=self._function_name,
|
96
|
+
function=self._function,
|
97
|
+
invocation_state=ProxiedInvocationState(
|
98
|
+
request.task_id, self._invocation_state_proxy_server
|
99
|
+
),
|
100
|
+
logger=self._logger,
|
101
|
+
).run()
|
102
|
+
|
103
|
+
def _check_task_routed_correctly(self, request: RunTaskRequest):
|
90
104
|
# Fail with internal error as this happened due to wrong task routing to this Server.
|
105
|
+
# If we run the wrongly routed task then it can steal data from this Server if it belongs
|
106
|
+
# to a different customer.
|
91
107
|
if request.namespace != self._namespace:
|
92
108
|
raise ValueError(
|
93
109
|
f"This Function Executor is not initialized for this namespace {request.namespace}"
|
94
110
|
)
|
95
111
|
if request.graph_name != self._graph_name:
|
96
112
|
raise ValueError(
|
97
|
-
f"This Function Executor is not initialized for this
|
113
|
+
f"This Function Executor is not initialized for this graph_name {request.graph_name}"
|
98
114
|
)
|
99
115
|
if request.graph_version != self._graph_version:
|
100
116
|
raise ValueError(
|
101
|
-
f"This Function Executor is not initialized for this
|
117
|
+
f"This Function Executor is not initialized for this graph_version {request.graph_version}"
|
102
118
|
)
|
103
119
|
if request.function_name != self._function_name:
|
104
120
|
raise ValueError(
|
105
|
-
f"This Function Executor is not initialized for this
|
121
|
+
f"This Function Executor is not initialized for this function_name {request.function_name}"
|
106
122
|
)
|
107
|
-
|
108
|
-
return RunTaskHandler(
|
109
|
-
request=request,
|
110
|
-
graph_name=self._graph_name,
|
111
|
-
graph_version=self._graph_version,
|
112
|
-
function_name=self._function_name,
|
113
|
-
function=self._function,
|
114
|
-
invocation_state=ProxiedInvocationState(
|
115
|
-
request.task_id, self._invocation_state_proxy_server
|
116
|
-
),
|
117
|
-
logger=self._logger,
|
118
|
-
).run()
|
@@ -1,6 +1,6 @@
|
|
1
|
-
indexify/cli/cli.py,sha256=
|
1
|
+
indexify/cli/cli.py,sha256=y6JNaMd5by7_v3jE1iah1krlvfzbN4r5A2WkgGTy1Ts,11427
|
2
2
|
indexify/executor/README.md,sha256=ozC6_hMkhQQNVCMEpBxwiUALz6lwErPQxNxQfQDqnG4,2029
|
3
|
-
indexify/executor/api_objects.py,sha256=
|
3
|
+
indexify/executor/api_objects.py,sha256=k5tKYxaWml0sSECoEDzamCYeJnlD7zO2M7E_qGwyMrg,1032
|
4
4
|
indexify/executor/downloader.py,sha256=Vrq1dAW4BifG62tlqFnImiMxdezIgOZcByTRnhDsnnw,6457
|
5
5
|
indexify/executor/executor.py,sha256=lln0p0cVN2aNY3bsHFp7Phbaa2q9gnQABi1xEPxo1Nc,5859
|
6
6
|
indexify/executor/function_executor/function_executor.py,sha256=a9pAWQWDLJL-i5bp1PEMD2eMYOTvXAh_1jQsXcL_JCQ,5226
|
@@ -34,11 +34,11 @@ indexify/function_executor/proto/function_executor_pb2.pyi,sha256=TQEOl3W1s4fxtp
|
|
34
34
|
indexify/function_executor/proto/function_executor_pb2_grpc.py,sha256=xrqIDrcl1PTyQTGAAGrgSDKEtZilC445Op0tJ7LmS5Q,8716
|
35
35
|
indexify/function_executor/proto/message_validator.py,sha256=OKXPYgy5L9c-spnV9Zjv7PA_yxwzvykfhbYylYx8cwQ,1456
|
36
36
|
indexify/function_executor/server.py,sha256=tJzUy_v4BT8Le9G3hgtiuDJo9YVFkAU2dVISSsX36II,1061
|
37
|
-
indexify/function_executor/service.py,sha256=
|
37
|
+
indexify/function_executor/service.py,sha256=i3bI7RSKSr3cDiNFoZdl4TSY_SMKlXBXPdExjvaAoBY,5606
|
38
38
|
indexify/utils/README.md,sha256=2g8-H9GopacOW4YrViZc0QsaJPtK-Fox7GyfX01kcDk,86
|
39
39
|
indexify/utils/http_client.py,sha256=deMlmAu4E_ZXV3blCdWNag3uO_cyD-GsMZjFFmO5r7s,3541
|
40
40
|
indexify/utils/logging.py,sha256=c6NwzY7uVHMRJc8f2w2KF36rNkeZVoQfGdq7suIg9s8,2025
|
41
|
-
indexify-0.3.
|
42
|
-
indexify-0.3.
|
43
|
-
indexify-0.3.
|
44
|
-
indexify-0.3.
|
41
|
+
indexify-0.3.3.dist-info/METADATA,sha256=VLMu3g8ZamLGLCjjqwPrBxqg8ZStvSZooP9ITl-BbHw,1383
|
42
|
+
indexify-0.3.3.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
43
|
+
indexify-0.3.3.dist-info/entry_points.txt,sha256=pJG0YRnypesbiNJHuObfHEkjk0p_ZvEDTyyTH0kGVTY,108
|
44
|
+
indexify-0.3.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|