diff --git a/doc/source/examples/notebooks.rst b/doc/source/examples/notebooks.rst index 08a4b1f6a2..c13baeb401 100644 --- a/doc/source/examples/notebooks.rst +++ b/doc/source/examples/notebooks.rst @@ -119,7 +119,7 @@ Production Configurations and Integrations Example Helm Deployments Max gRPC Message Size - REST timeouts + Configurable timeouts Deploy Multiple Seldon Core Operators Protocol Examples Custom Protobuf Data Example diff --git a/doc/source/examples/rest_timeouts.nblink b/doc/source/examples/timeouts.nblink similarity index 100% rename from doc/source/examples/rest_timeouts.nblink rename to doc/source/examples/timeouts.nblink diff --git a/doc/source/python/developer_notes.md b/doc/source/python/developer_notes.md new file mode 100644 index 0000000000..59a10d1cbf --- /dev/null +++ b/doc/source/python/developer_notes.md @@ -0,0 +1,49 @@ +# Development Tips + + +## Running locally for testing + +Sometimes it is useful to be able to test your model locally without the need to build image with s2i or docker. + +This can be easily done with `seldon-core` as its installed the CLI command that starts the microservice. + +Assuming we have a simple model saved in `MyModel.py` file: +```python +class MyModel: + + def predict(self, X, features_names=None): + """ + Return a prediction. + + Parameters + ---------- + X : array-like + feature_names : array of feature names (optional) + """ + print("Predict called - will run identity function") + return X +``` + +We can start Seldon Core microservice with +```bash +seldon-core-microservice MyModel --service-type MODEL +``` + +Then in other terminal we can send `curl` requests to test REST endpoint: +```bash +curl http://localhost:9000/api/v1.0/predictions \ + -H 'Content-Type: application/json' \ + -d '{"data": {"names": ["input"], "ndarray": ["data"]}}' +``` + + +And assuming that `seldon-core` code is accessible at `${SELDON_CORE_DIR}` we can use `grpcurl` to send gRPC request: +```bash +cd ${SELDON_CORE_DIR}/executor/proto && grpcurl \ + -d '{"data": {"names": ["input"], "ndarray": ["data"]}}' \ + -plaintext -proto ./prediction.proto 0.0.0.0:5000 seldon.protos.Seldon/Predict +``` + +The `grpcurl` tool can be obtained using binaries released on [GitHub](https://github.com/fullstorydev/grpcurl) or using [asdf-vm](https://github.com/asdf-vm/asdf-plugins). + +See [Python Server](./python_server.html#configuration) documentation for config options. diff --git a/doc/source/python/index.rst b/doc/source/python/index.rst index 27f4b13b7f..2051690ca0 100644 --- a/doc/source/python/index.rst +++ b/doc/source/python/index.rst @@ -17,6 +17,6 @@ You can use the following links to navigate the Python seldon-core module: Create image with S2I Create image with a Dockerfile Seldon Python server configuration - Calling the Seldon API with the Seldon Python client - Python API reference - + Calling the Seldon API with the Seldon Python client + Python API reference + Development Tips diff --git a/examples/ambassador/canary/ambassador_canary.ipynb b/examples/ambassador/canary/ambassador_canary.ipynb index 17325dd1fd..e880031981 100644 --- a/examples/ambassador/canary/ambassador_canary.ipynb +++ b/examples/ambassador/canary/ambassador_canary.ipynb @@ -25,7 +25,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Error from server (AlreadyExists): namespaces \"seldon\" already exists\r\n" + "Error from server (AlreadyExists): namespaces \"seldon\" already exists\n" ] } ], @@ -42,7 +42,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Context \"kind-kind\" modified.\r\n" + "Context \"kind-seldon\" modified.\n" ] } ], @@ -72,7 +72,7 @@ { "data": { "text/plain": [ - "'1.5.0-dev'" + "'1.6.0-dev'" ] }, "execution_count": 4, @@ -97,7 +97,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -130,14 +130,14 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io/example created\r\n" + "seldondeployment.machinelearning.seldon.io/example created\n" ] } ], @@ -147,7 +147,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -172,7 +172,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -189,7 +189,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -204,12 +204,12 @@ " tensor {\n", " shape: 1\n", " shape: 1\n", - " values: 0.5531305252881753\n", + " values: 0.71309135369705\n", " }\n", "}\n", "\n", "Response:\n", - "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.08599584459790496]}}, 'meta': {}}\n" + "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.09942988397161616]}}, 'meta': {'requestPath': {'classifier': 'seldonio/mock_classifier:1.6.0-dev'}}}\n" ] } ], @@ -230,7 +230,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -280,14 +280,15 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io/example created\r\n" + "Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply\n", + "seldondeployment.machinelearning.seldon.io/example configured\n" ] } ], @@ -297,13 +298,14 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "Waiting for deployment \"example-canary-0-classifier\" rollout to finish: 0 of 1 updated replicas are available...\n", "deployment \"example-canary-0-classifier\" successfully rolled out\n", "deployment \"example-main-0-classifier\" successfully rolled out\n" ] @@ -323,7 +325,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -337,15 +339,15 @@ " tensor {\n", " shape: 1\n", " shape: 1\n", - " values: 0.08077854180978328\n", + " values: 0.8694648161558428\n", " }\n", "}\n", "\n", "Response:\n", - "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.0554153788429373]}}, 'meta': {}}" + "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.11433542420010957]}}, 'meta': {'requestPath': {'classifier': 'seldonio/mock_classifier:1.6.0-dev'}}}" ] }, - "execution_count": 28, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -356,7 +358,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ @@ -367,34 +369,41 @@ " r = sc.predict(gateway=\"ambassador\",transport=\"rest\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Following checks number of prediction requests processed by default/canary predictors respectively." + ] + }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ - "default_count=!kubectl logs $(kubectl get pod -lseldon-app=example-main -o jsonpath='{.items[0].metadata.name}') classifier | grep \"/predict\" | wc -l " + "default_count=!kubectl logs $(kubectl get pod -lseldon-app=example-main -o jsonpath='{.items[0].metadata.name}') classifier | grep \"root:predict\" | wc -l " ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ - "canary_count=!kubectl logs $(kubectl get pod -lseldon-app=example-canary -o jsonpath='{.items[0].metadata.name}') classifier | grep \"/predict\" | wc -l" + "canary_count=!kubectl logs $(kubectl get pod -lseldon-app=example-canary -o jsonpath='{.items[0].metadata.name}') classifier | grep \"root:predict\" | wc -l" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "0.2948717948717949\n" + "0.32894736842105265\n" ] } ], @@ -406,27 +415,20 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io \"example\" deleted\r\n" + "seldondeployment.machinelearning.seldon.io \"example\" deleted\n" ] } ], "source": [ "!kubectl delete -f canary.yaml" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -446,7 +448,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.8" + "version": "3.8.6" }, "varInspector": { "cols": { @@ -479,5 +481,5 @@ } }, "nbformat": 4, - "nbformat_minor": 1 + "nbformat_minor": 4 } diff --git a/examples/ambassador/headers/ambassador_headers.ipynb b/examples/ambassador/headers/ambassador_headers.ipynb index 3c5707b353..fc378db4be 100644 --- a/examples/ambassador/headers/ambassador_headers.ipynb +++ b/examples/ambassador/headers/ambassador_headers.ipynb @@ -27,7 +27,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Error from server (AlreadyExists): namespaces \"seldon\" already exists\r\n" + "Error from server (AlreadyExists): namespaces \"seldon\" already exists\n" ] } ], @@ -44,7 +44,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Context \"kind-kind\" modified.\r\n" + "Context \"kind-seldon\" modified.\n" ] } ], @@ -74,7 +74,7 @@ { "data": { "text/plain": [ - "'1.5.0-dev'" + "'1.6.0-dev'" ] }, "execution_count": 4, @@ -99,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -132,14 +132,14 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io/example created\r\n" + "seldondeployment.machinelearning.seldon.io/example created\n" ] } ], @@ -149,7 +149,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -174,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -191,7 +191,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -206,12 +206,12 @@ " tensor {\n", " shape: 1\n", " shape: 1\n", - " values: 0.6683377893898669\n", + " values: 0.43446257172493064\n", " }\n", "}\n", "\n", "Response:\n", - "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.0954937100180911]}}, 'meta': {}}\n" + "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.07711519385598731]}}, 'meta': {'requestPath': {'classifier': 'seldonio/mock_classifier:1.6.0-dev'}}}\n" ] } ], @@ -241,7 +241,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -277,14 +277,14 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io/example-header created\r\n" + "seldondeployment.machinelearning.seldon.io/example-header created\n" ] } ], @@ -294,7 +294,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -319,7 +319,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -334,12 +334,12 @@ " tensor {\n", " shape: 1\n", " shape: 1\n", - " values: 0.015688371980047133\n", + " values: 0.6178977707280904\n", " }\n", "}\n", "\n", "Response:\n", - "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.052105223663186165]}}, 'meta': {}}\n" + "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.09122497185647573]}}, 'meta': {'requestPath': {'classifier': 'seldonio/mock_classifier:1.6.0-dev'}}}\n" ] } ], @@ -350,16 +350,16 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ - "default_count=!kubectl logs $(kubectl get pod -lseldon-app=example-single -o jsonpath='{.items[0].metadata.name}') classifier | grep \"/predict\" | wc -l " + "default_count=!kubectl logs $(kubectl get pod -lseldon-app=example-single -o jsonpath='{.items[0].metadata.name}') classifier | grep \"root.predict\" | wc -l " ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -384,7 +384,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -399,12 +399,12 @@ " tensor {\n", " shape: 1\n", " shape: 1\n", - " values: 0.6339240340443978\n", + " values: 0.4904085439061101\n", " }\n", "}\n", "\n", "Response:\n", - "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.0925623293728051]}}, 'meta': {}}\n" + "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.08119217418182277]}}, 'meta': {'requestPath': {'classifier': 'seldonio/mock_classifier:1.6.0-dev'}}}\n" ] } ], @@ -415,16 +415,16 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ - "header_count=!kubectl logs $(kubectl get pod -lseldon-app=example-header-single -o jsonpath='{.items[0].metadata.name}') classifier | grep \"/predict\" | wc -l " + "header_count=!kubectl logs $(kubectl get pod -lseldon-app=example-header-single -o jsonpath='{.items[0].metadata.name}') classifier | grep \"root.predict\" | wc -l " ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -442,14 +442,14 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io \"example\" deleted\r\n" + "seldondeployment.machinelearning.seldon.io \"example\" deleted\n" ] } ], @@ -459,27 +459,20 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io \"example-header\" deleted\r\n" + "seldondeployment.machinelearning.seldon.io \"example-header\" deleted\n" ] } ], "source": [ "!kubectl delete -f model_with_header.yaml" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -499,7 +492,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.8" + "version": "3.8.6" }, "varInspector": { "cols": { @@ -532,5 +525,5 @@ } }, "nbformat": 4, - "nbformat_minor": 1 + "nbformat_minor": 4 } diff --git a/examples/ambassador/shadow/ambassador_shadow.ipynb b/examples/ambassador/shadow/ambassador_shadow.ipynb index 370884fbdb..4905f051d7 100644 --- a/examples/ambassador/shadow/ambassador_shadow.ipynb +++ b/examples/ambassador/shadow/ambassador_shadow.ipynb @@ -29,7 +29,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Error from server (AlreadyExists): namespaces \"seldon\" already exists\r\n" + "Error from server (AlreadyExists): namespaces \"seldon\" already exists\n" ] } ], @@ -39,16 +39,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Context \"kind-seldon\" modified.\n" + ] + } + ], "source": [ "!kubectl config set-context $(kubectl config current-context) --namespace=seldon" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -62,16 +70,16 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'1.5.0-dev'" + "'1.6.0-dev'" ] }, - "execution_count": 3, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -93,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -126,14 +134,14 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io/example created\r\n" + "seldondeployment.machinelearning.seldon.io/example configured\n" ] } ], @@ -143,14 +151,14 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "deployment \"example-default-0-classifier\" successfully rolled out\r\n" + "deployment \"example-default-0-classifier\" successfully rolled out\n" ] } ], @@ -167,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -184,7 +192,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -199,12 +207,12 @@ " tensor {\n", " shape: 1\n", " shape: 1\n", - " values: 0.6517840856894687\n", + " values: 0.9967112738898524\n", " }\n", "}\n", "\n", "Response:\n", - "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.09407343218921792]}}, 'meta': {}}\n" + "{'data': {'names': ['proba'], 'tensor': {'shape': [1, 1], 'values': [0.12786654068631786]}}, 'meta': {'requestPath': {'classifier': 'seldonio/mock_classifier:1.6.0-dev'}}}\n" ] } ], @@ -224,7 +232,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -272,14 +280,14 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "seldondeployment.machinelearning.seldon.io/example configured\r\n" + "seldondeployment.machinelearning.seldon.io/example configured\n" ] } ], @@ -289,7 +297,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -316,7 +324,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -326,25 +334,25 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ - "default_count=!kubectl logs $(kubectl get pod -lseldon-app=example-default -o jsonpath='{.items[0].metadata.name}') classifier | grep \"/predict\" | wc -l " + "default_count=!kubectl logs $(kubectl get pod -lseldon-app=example-default -o jsonpath='{.items[0].metadata.name}') classifier | grep \"root.predict\" | wc -l " ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ - "shadow_count=!kubectl logs $(kubectl get pod -lseldon-app=example-shadow -o jsonpath='{.items[0].metadata.name}') classifier | grep \"/predict\" | wc -l " + "shadow_count=!kubectl logs $(kubectl get pod -lseldon-app=example-shadow -o jsonpath='{.items[0].metadata.name}') classifier | grep \"root.predict\" | wc -l " ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -372,27 +380,20 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Error from server (NotFound): error when deleting \"model.yaml\": seldondeployments.machinelearning.seldon.io \"example\" not found\r\n" + "seldondeployment.machinelearning.seldon.io \"example\" deleted\n" ] } ], "source": [ "!kubectl delete -f model.yaml" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -412,7 +413,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.8" + "version": "3.8.6" }, "varInspector": { "cols": { @@ -445,5 +446,5 @@ } }, "nbformat": 4, - "nbformat_minor": 1 + "nbformat_minor": 4 } diff --git a/examples/models/mean_classifier/MeanClassifier.py b/examples/models/mean_classifier/MeanClassifier.py index 0c8ee78b75..f3bbf24214 100644 --- a/examples/models/mean_classifier/MeanClassifier.py +++ b/examples/models/mean_classifier/MeanClassifier.py @@ -1,17 +1,24 @@ import numpy as np import math +import time +import logging def f(x): return 1/(1+math.exp(-x)) class MeanClassifier(object): - def __init__(self, intValue=0): + def __init__(self, intValue=0, delaySecs=0): self.class_names = ["proba"] - assert type(intValue) == int, "intValue parameters must be an integer" + assert type(intValue) == int, "intValue parameter must be an integer" self.int_value = intValue + logging.info("intValue set to %d",intValue) - print("Loading model here") + assert type(delaySecs) == int, "delaySecs parameter must be an integer" + self.delay_secs = delaySecs + logging.info("Delay secs set to %d",delaySecs) + + logging.info("loading model here") X = np.load(open("model.npy",'rb'), encoding='latin1') self.threshold_ = X.mean() + self.int_value @@ -20,10 +27,14 @@ def _meaning(self, x): return f(x.mean()-self.threshold_) def predict(self, X, feature_names): - print(X) + logging.info("Input %s",X) X = np.array(X) assert len(X.shape) == 2, "Incorrect shape" + if self.delay_secs > 0: + logging.info("Delaying %d secs",self.delay_secs) + time.sleep(self.delay_secs) + return [[self._meaning(x)] for x in X] def health_status(self): diff --git a/notebooks/resources/model_long_timeouts.json b/notebooks/resources/model_long_timeouts.json index f0d18c3c37..127a43adb2 100644 --- a/notebooks/resources/model_long_timeouts.json +++ b/notebooks/resources/model_long_timeouts.json @@ -1,49 +1,24 @@ -{ - "apiVersion": "machinelearning.seldon.io/v1alpha2", - "kind": "SeldonDeployment", - "metadata": { - "labels": { - "app": "seldon" - }, - "name": "model-long-timeout" - }, - "spec": { - "annotations": { - "deployment_version": "v1", - "seldon.io/rest-timeout":"100000", - "seldon.io/grpc-timeout":"100000" - }, - "name": "long-to", - "predictors": [ - { - "componentSpecs": [{ - "spec": { - "containers": [ - { - "image": "seldonio/mock_classifier:1.5.0-dev", - "imagePullPolicy": "IfNotPresent", - "name": "classifier", - "resources": { - "requests": { - "memory": "1Mi" - } - } - } - ], - "terminationGracePeriodSeconds": 20 - } - }], - "graph": { - "children": [], - "name": "classifier", - "type": "MODEL" - }, - "name": "test", - "replicas": 1, - "annotations": { - "predictor_version" : "v1" - } - } - ] - } -} +apiVersion: machinelearning.seldon.io/v1 +kind: SeldonDeployment +metadata: + name: seldon-model +spec: + annotations: + seldon.io/rest-timeout: "5000" + seldon.io/grpc-timeout: "5000" + predictors: + - componentSpecs: + - spec: + containers: + - image: seldonio/mock_classifier:1.6.0-dev + name: classifier + graph: + children: [] + name: classifier + type: MODEL + parameters: + - name: delaySecs + type: INT + value: "2" + name: example + replicas: 1 diff --git a/notebooks/resources/model_short_timeouts.json b/notebooks/resources/model_short_timeouts.json index 6c76fd9488..5ebe8794a7 100644 --- a/notebooks/resources/model_short_timeouts.json +++ b/notebooks/resources/model_short_timeouts.json @@ -1,54 +1,24 @@ -{ - "apiVersion": "machinelearning.seldon.io/v1alpha2", - "kind": "SeldonDeployment", - "metadata": { - "labels": { - "app": "seldon" - }, - "name": "seldon-deployment-example" - }, - "spec": { - "annotations": { - "project_name": "FX Market Prediction", - "deployment_version": "v1", - "seldon.io/rest-read-timeout": "1" - }, - "name": "test-deployment", - "predictors": [ - { - "componentSpecs": [ - { - "spec": { - "containers": [ - { - "image": "seldonio/mock_classifier:1.0", - "imagePullPolicy": "IfNotPresent", - "name": "classifier", - "resources": { - "requests": { - "memory": "1Mi" - } - } - } - ], - "terminationGracePeriodSeconds": 20 - } - } - ], - "graph": { - "children": [], - "name": "classifier", - "endpoint": { - "type": "REST" - }, - "type": "MODEL" - }, - "name": "fx-market-predictor", - "replicas": 1, - "annotations": { - "predictor_version": "v1" - } - } - ] - } -} +apiVersion: machinelearning.seldon.io/v1 +kind: SeldonDeployment +metadata: + name: seldon-model +spec: + annotations: + seldon.io/rest-timeout: "1000" + seldon.io/grpc-timeout: "1000" + predictors: + - componentSpecs: + - spec: + containers: + - image: seldonio/mock_classifier:1.6.0-dev + name: classifier + graph: + children: [] + name: classifier + type: MODEL + parameters: + - name: delaySecs + type: INT + value: "2" + name: example + replicas: 1 diff --git a/notebooks/timeouts.ipynb b/notebooks/timeouts.ipynb index 651d236892..400d9af823 100644 --- a/notebooks/timeouts.ipynb +++ b/notebooks/timeouts.ipynb @@ -11,170 +11,302 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "## Prerequisites\n", + "\n", + " * Kubernetes cluster with kubectl authorized\n", + " * curl and grpcurl installed\n", + "\n", "## Setup Seldon Core\n", "\n", - "Use the setup notebook to [Setup Cluster](https://docs.seldon.io/projects/seldon-core/en/latest/examples/seldon_core_setup.html#Setup-Cluster) with [Ambassador Ingress](https://docs.seldon.io/projects/seldon-core/en/latest/examples/seldon_core_setup.html#Ambassador) and [Install Seldon Core](https://docs.seldon.io/projects/seldon-core/en/latest/examples/seldon_core_setup.html#Install-Seldon-Core). Instructions [also online](https://docs.seldon.io/projects/seldon-core/en/latest/examples/seldon_core_setup.html)." + "Use the setup notebook to [Setup Cluster](https://docs.seldon.io/projects/seldon-core/en/latest/examples/seldon_core_setup.html) to setup Seldon Core with an ingress - either Ambassador or Istio.\n", + "\n", + "Then port-forward to that ingress on localhost:8003 in a separate terminal either with:\n", + "\n", + " * Ambassador: `kubectl port-forward $(kubectl get pods -n seldon -l app.kubernetes.io/name=ambassador -o jsonpath='{.items[0].metadata.name}') -n seldon 8003:8080`\n", + " * Istio: `kubectl port-forward $(kubectl get pods -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') -n istio-system 8003:8080`" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 38, "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "namespace/seldon created\r\n" + ] + } + ], "source": [ - "Illustration of both REST and gRPC requests. " + "!kubectl create namespace seldon" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 39, "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Context \"kind-kind\" modified.\r\n" + ] + } + ], "source": [ - "### Short timeouts deployment file\n", - "Below is the outputs of the Seldon config file required to set custom timeouts.\n", - "\n", - "First we'll show how we can set a short lived example by setting the `\"seldon.io/rest-read-timeout\":\"1\"` annotation." + "!kubectl config set-context $(kubectl config current-context) --namespace=seldon" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, + "execution_count": 40, + "metadata": {}, "outputs": [], "source": [ - "%%writefile resources/model_short_timeouts.json\n", - "{\n", - " \"apiVersion\": \"machinelearning.seldon.io/v1alpha2\",\n", - " \"kind\": \"SeldonDeployment\",\n", - " \"metadata\": {\n", - " \"labels\": {\n", - " \"app\": \"seldon\"\n", - " },\n", - " \"name\": \"seldon-deployment-example\"\n", - " },\n", - " \"spec\": {\n", - " \"annotations\": {\n", - " \"project_name\": \"FX Market Prediction\",\n", - " \"deployment_version\": \"v1\",\n", - "\t \"seldon.io/rest-read-timeout\":\"1\"\n", - " },\n", - " \"name\": \"test-deployment\",\n", - " \"predictors\": [\n", - " {\n", - " \"componentSpecs\": [{\n", - " \"spec\": {\n", - " \"containers\": [\n", - " {\n", - " \"image\": \"seldonio/mock_classifier:1.0\",\n", - " \"imagePullPolicy\": \"IfNotPresent\",\n", - " \"name\": \"classifier\",\n", - " \"resources\": {\n", - " \"requests\": {\n", - " \"memory\": \"1Mi\"\n", - " }\n", - " }\n", - " }\n", - " ],\n", - " \"terminationGracePeriodSeconds\": 20\n", - " }\n", - " }],\n", - " \"graph\": {\n", - " \"children\": [],\n", - " \"name\": \"classifier\",\n", - " \"endpoint\": {\n", - "\t\t\t\"type\" : \"REST\"\n", - "\t\t },\n", - " \"type\": \"MODEL\"\n", - " },\n", - " \"name\": \"fx-market-predictor\",\n", - " \"replicas\": 1,\n", - "\t\t\"annotations\": {\n", - "\t\t \"predictor_version\" : \"v1\"\n", - "\t\t}\n", - " }\n", - " ]\n", - " }\n", - "}" + "from IPython.core.magic import register_line_cell_magic\n", + "\n", + "@register_line_cell_magic\n", + "def writetemplate(line, cell):\n", + " with open(line, 'w') as f:\n", + " f.write(cell.format(**globals()))" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 41, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'1.6.0-dev'" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "## Seldon Deployment with Short Timeout" + "VERSION=!cat ../version.txt\n", + "VERSION=VERSION[0]\n", + "VERSION" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can then apply this Seldon Deployment file we defined above in the `seldon` namespace." + "## Configure Istio\n", + "\n", + "For this example we will create the default istio gateway for seldon which needs to be called `seldon-gateway`. You can supply your own gateway by adding to your SeldonDeployments resources the annotation `seldon.io/istio-gateway` with values the name of your istio gateway." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting resources/seldon-gateway.yaml\n" + ] + } + ], "source": [ - "!kubectl apply -f resources/model_short_timeouts.json -n seldon" + "%%writefile resources/seldon-gateway.yaml\n", + "apiVersion: networking.istio.io/v1alpha3\n", + "kind: Gateway\n", + "metadata:\n", + " name: seldon-gateway\n", + " namespace: istio-system\n", + "spec:\n", + " selector:\n", + " istio: ingressgateway # use istio default controller\n", + " servers:\n", + " - port:\n", + " number: 80\n", + " name: http\n", + " protocol: HTTP\n", + " hosts:\n", + " - \"*\"" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gateway.networking.istio.io/seldon-gateway created\r\n" + ] + } + ], + "source": [ + "!kubectl create -f resources/seldon-gateway.yaml -n istio-system" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "And wait until the resource runs correctly." + "### Short timeouts deployment file\n", + "Below is the outputs of the Seldon config file required to set custom timeouts.\n", + "\n", + "First we'll show how we can set a short lived example by setting the `\"seldon.io/rest-read-timeout\":\"1\"` annotation." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, + "execution_count": 57, + "metadata": {}, "outputs": [], "source": [ - "!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=seldon-deployment-example -o jsonpath='{.items[0].metadata.name}')" + "%%writetemplate resources/model_short_timeouts.json\n", + "apiVersion: machinelearning.seldon.io/v1\n", + "kind: SeldonDeployment\n", + "metadata:\n", + " name: seldon-model\n", + "spec:\n", + " annotations:\n", + " seldon.io/rest-timeout: \"1000\"\n", + " seldon.io/grpc-timeout: \"1000\"\n", + " predictors:\n", + " - componentSpecs:\n", + " - spec:\n", + " containers:\n", + " - image: seldonio/mock_classifier:1.6.0-dev\n", + " name: classifier\n", + " graph:\n", + " children: []\n", + " name: classifier\n", + " type: MODEL\n", + " parameters:\n", + " - name: delaySecs\n", + " type: INT\n", + " value: \"2\" \n", + " name: example\n", + " replicas: 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now that it's deployed we can send requests to the model using the python client" + "We can then apply this Seldon Deployment file we defined above in the `seldon` namespace." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 58, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "seldondeployment.machinelearning.seldon.io/seldon-model configured\r\n" + ] + } + ], "source": [ - "from seldon_core.seldon_client import SeldonClient\n", - "sc = SeldonClient(deployment_name=\"seldon-deployment-example\",namespace=\"seldon\")" + "!kubectl apply -f resources/model_short_timeouts.json -n seldon" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This next request should fail as the timeout is too short" + "And wait until the resource runs correctly." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 59, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "deployment \"seldon-model-example-0-classifier\" successfully rolled out\r\n" + ] + } + ], + "source": [ + "!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=seldon-model -o jsonpath='{.items[0].metadata.name}')" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HTTP/1.1 500 Internal Server Error\r", + "\r\n", + "access-control-allow-headers: Accept, Accept-Encoding, Authorization, Content-Length, Content-Type, X-CSRF-Token\r", + "\r\n", + "access-control-allow-methods: OPTIONS,POST\r", + "\r\n", + "access-control-allow-origin: *\r", + "\r\n", + "seldon-puid: b8937292-f055-45a6-a3c4-c887af2e88ae\r", + "\r\n", + "x-content-type-options: nosniff\r", + "\r\n", + "date: Tue, 08 Dec 2020 10:51:03 GMT\r", + "\r\n", + "content-length: 0\r", + "\r\n", + "x-envoy-upstream-service-time: 1000\r", + "\r\n", + "server: istio-envoy\r", + "\r\n", + "\r", + "\r\n" + ] + } + ], + "source": [ + "!curl -i -d '{\"data\": {\"ndarray\":[[1.0, 2.0, 5.0]]}}' -X POST http://localhost:8003/seldon/seldon/seldon-model/api/v1.0/predictions -H \"Content-Type: application/json\"" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ERROR:\r\n", + " Code: DeadlineExceeded\r\n", + " Message: Deadline Exceeded\r\n" + ] + } + ], "source": [ - "r = sc.predict(gateway=\"ambassador\",transport=\"rest\")\n", - "print(r)" + "!cd ../executor/proto && grpcurl -d '{\"data\":{\"ndarray\":[[1.0,2.0,5.0]]}}' \\\n", + " -rpc-header seldon:seldon-model -rpc-header namespace:seldon \\\n", + " -plaintext \\\n", + " -proto ./prediction.proto 0.0.0.0:8003 seldon.protos.Seldon/Predict" ] }, { @@ -186,11 +318,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 63, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "seldondeployment.machinelearning.seldon.io \"seldon-model\" deleted\r\n" + ] + } + ], "source": [ "!kubectl delete -f resources/model_short_timeouts.json" ] @@ -201,70 +341,42 @@ "source": [ "## Seldon Deployment with Long Timeout\n", "\n", - "Now we can have a look at how we can set a deployment with a longer timeout by setting the annotations `\"seldon.io/rest-timeout\":\"100000\"`, and `\"seldon.io/grpc-timeout\":\"100000\"`." + "Now we can have a look at how we can set a deployment with a longer timeout." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "metadata": { "scrolled": true }, "outputs": [], "source": [ - "%%writefile resources/model_long_timeouts.json\n", - "{\n", - " \"apiVersion\": \"machinelearning.seldon.io/v1alpha2\",\n", - " \"kind\": \"SeldonDeployment\",\n", - " \"metadata\": {\n", - " \"labels\": {\n", - " \"app\": \"seldon\"\n", - " },\n", - " \"name\": \"model-long-timeout\"\n", - " },\n", - " \"spec\": {\n", - " \"annotations\": {\n", - " \"deployment_version\": \"v1\",\n", - "\t \"seldon.io/rest-timeout\":\"100000\",\n", - "\t \"seldon.io/grpc-timeout\":\"100000\"\n", - " },\n", - " \"name\": \"long-to\",\n", - " \"predictors\": [\n", - " {\n", - " \"componentSpecs\": [{\n", - " \"spec\": {\n", - " \"containers\": [\n", - " {\n", - " \"image\": \"seldonio/mock_classifier_grpc:1.5\",\n", - " \"imagePullPolicy\": \"IfNotPresent\",\n", - " \"name\": \"classifier\",\n", - " \"resources\": {\n", - " \"requests\": {\n", - " \"memory\": \"1Mi\"\n", - " }\n", - " }\n", - " }\n", - " ],\n", - " \"terminationGracePeriodSeconds\": 20\n", - " }\n", - " }],\n", - " \"graph\": {\n", - " \"children\": [],\n", - " \"name\": \"classifier\",\n", - " \"endpoint\": {\n", - "\t\t\t\"type\" : \"GRPC\"\n", - "\t\t },\n", - " \"type\": \"MODEL\"\n", - " },\n", - " \"name\": \"test\",\n", - " \"replicas\": 1,\n", - "\t\t\"annotations\": {\n", - "\t\t \"predictor_version\" : \"v1\"\n", - "\t\t}\n", - " }\n", - " ]\n", - " }\n", - "}" + "%%writetemplate resources/model_long_timeouts.json\n", + "apiVersion: machinelearning.seldon.io/v1\n", + "kind: SeldonDeployment\n", + "metadata:\n", + " name: seldon-model\n", + "spec:\n", + " annotations:\n", + " seldon.io/rest-timeout: \"5000\"\n", + " seldon.io/grpc-timeout: \"5000\"\n", + " predictors:\n", + " - componentSpecs:\n", + " - spec:\n", + " containers:\n", + " - image: seldonio/mock_classifier:1.6.0-dev\n", + " name: classifier\n", + " graph:\n", + " children: []\n", + " name: classifier\n", + " type: MODEL\n", + " parameters:\n", + " - name: delaySecs\n", + " type: INT\n", + " value: \"2\" \n", + " name: example\n", + " replicas: 1" ] }, { @@ -276,24 +388,41 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 65, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "seldondeployment.machinelearning.seldon.io/seldon-model created\r\n" + ] + } + ], "source": [ "!kubectl apply -f resources/model_long_timeouts.json -n seldon" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 66, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for deployment \"seldon-model-example-0-classifier\" rollout to finish: 0 of 1 updated replicas are available...\n", + "deployment \"seldon-model-example-0-classifier\" successfully rolled out\n" + ] + } + ], "source": [ - "!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=model-long-timeout -o jsonpath='{.items[0].metadata.name}')" + "!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=seldon-model -o jsonpath='{.items[0].metadata.name}')" ] }, { @@ -305,15 +434,106 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 67, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HTTP/1.1 200 OK\r", + "\r\n", + "access-control-allow-headers: Accept, Accept-Encoding, Authorization, Content-Length, Content-Type, X-CSRF-Token\r", + "\r\n", + "access-control-allow-methods: OPTIONS,POST\r", + "\r\n", + "access-control-allow-origin: *\r", + "\r\n", + "content-type: application/json\r", + "\r\n", + "seldon-puid: 1525aa31-e857-46f7-b583-8cae93e71a52\r", + "\r\n", + "x-content-type-options: nosniff\r", + "\r\n", + "date: Tue, 08 Dec 2020 10:52:48 GMT\r", + "\r\n", + "content-length: 138\r", + "\r\n", + "x-envoy-upstream-service-time: 2010\r", + "\r\n", + "server: istio-envoy\r", + "\r\n", + "\r", + "\r\n", + "{\"data\":{\"names\":[\"proba\"],\"ndarray\":[[0.43782349911420193]]},\"meta\":{\"requestPath\":{\"classifier\":\"seldonio/mock_classifier:1.6.0-dev\"}}}\r\n" + ] + } + ], + "source": [ + "!curl -i -d '{\"data\": {\"ndarray\":[[1.0, 2.0, 5.0]]}}' -X POST http://localhost:8003/seldon/seldon/seldon-model/api/v1.0/predictions -H \"Content-Type: application/json\"" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\r\n", + " \"meta\": {\r\n", + " \"requestPath\": {\r\n", + " \"classifier\": \"seldonio/mock_classifier:1.6.0-dev\"\r\n", + " }\r\n", + " },\r\n", + " \"data\": {\r\n", + " \"names\": [\r\n", + " \"proba\"\r\n", + " ],\r\n", + " \"ndarray\": [\r\n", + " [\r\n", + " 0.43782349911420193\r\n", + " ]\r\n", + " ]\r\n", + " }\r\n", + "}\r\n" + ] + } + ], "source": [ - "r = sc.predict(gateway=\"ambassador\",transport=\"grpc\",deployment_name=\"model-long-timeout\")\n", - "print(r)" + "!cd ../executor/proto && grpcurl -d '{\"data\":{\"ndarray\":[[1.0,2.0,5.0]]}}' \\\n", + " -rpc-header seldon:seldon-model -rpc-header namespace:seldon \\\n", + " -plaintext \\\n", + " -proto ./prediction.proto 0.0.0.0:8003 seldon.protos.Seldon/Predict" ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "seldondeployment.machinelearning.seldon.io \"seldon-model\" deleted\r\n" + ] + } + ], + "source": [ + "!kubectl delete -f resources/model_long_timeouts.json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -333,7 +553,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.6.8" }, "varInspector": { "cols": { diff --git a/operator/controllers/seldondeployment_controller.go b/operator/controllers/seldondeployment_controller.go index 984f366cc5..a490b5700e 100644 --- a/operator/controllers/seldondeployment_controller.go +++ b/operator/controllers/seldondeployment_controller.go @@ -1648,6 +1648,14 @@ func (r *SeldonDeploymentReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e return ctrl.Result{}, err } + // Required for foreground deletion (e.g. ArgoCD does it) + if !instance.ObjectMeta.DeletionTimestamp.IsZero() { + // If Deletion Tiemstamp is set it means object is being deleted. + // We should take no action in this situation. + log.Info("Deletion timestamp is set. Doing nothing.") + return ctrl.Result{}, nil + } + // Check if we are not namespaced and should ignore this as its in a namespace managed by another operator if r.Namespace == "" { ns := &corev1.Namespace{} diff --git a/python/licenses/license.txt b/python/licenses/license.txt index a47d4a9f1e..fc01200ae0 100644 --- a/python/licenses/license.txt +++ b/python/licenses/license.txt @@ -1733,7 +1733,7 @@ Apache Software License grpcio-reflection -1.33.2 +1.34.0 Apache Software License Apache License @@ -2111,9 +2111,9 @@ THE SOFTWARE. numpy -1.19.4 +1.18.5 BSD -Copyright (c) 2005-2020, NumPy Developers. +Copyright (c) 2005-2019, NumPy Developers. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/python/licenses/license_info.csv b/python/licenses/license_info.csv index 243709cae8..7b9ad436b3 100644 --- a/python/licenses/license_info.csv +++ b/python/licenses/license_info.csv @@ -22,7 +22,7 @@ "google-pasta","0.2.0","Apache Software License" "grpcio","1.34.0","Apache Software License" "grpcio-opentracing","1.1.4","Apache Software License" -"grpcio-reflection","1.33.2","Apache Software License" +"grpcio-reflection","1.34.0","Apache Software License" "gunicorn","20.0.4","MIT License" "h5py","2.10.0","BSD License" "idna","2.10","BSD License" @@ -30,7 +30,7 @@ "itsdangerous","1.1.0","BSD License" "jaeger-client","4.3.0","Apache Software License" "jsonschema","3.2.0","MIT License" -"numpy","1.19.4","BSD" +"numpy","1.18.5","BSD" "oauthlib","3.1.0","BSD License" "opentracing","2.4.0","Apache Software License" "opt-einsum","3.3.0","MIT" diff --git a/python/setup.py b/python/setup.py index d15521edbf..f4165c064e 100644 --- a/python/setup.py +++ b/python/setup.py @@ -33,7 +33,7 @@ "opentracing >= 2.2.0, < 2.5.0", "jaeger-client >= 4.1.0, < 4.4.0", "grpcio-opentracing >= 1.1.4, < 1.2.0", - "grpcio-reflection==1.33.2", + "grpcio-reflection==1.34.0", "PyYAML<5.4", "gunicorn >= 19.9.0, < 20.1.0", "setuptools >= 41.0.0",