diff --git a/config/crd/serving.kserve.io_inferenceservices.yaml b/config/crd/serving.kserve.io_inferenceservices.yaml index 5c5ebb0eadc..3680558fa42 100644 --- a/config/crd/serving.kserve.io_inferenceservices.yaml +++ b/config/crd/serving.kserve.io_inferenceservices.yaml @@ -2319,6 +2319,24 @@ spec: - name type: object type: array + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object dnsConfig: properties: nameservers: @@ -4964,6 +4982,24 @@ spec: - name type: object type: array + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object dnsConfig: properties: nameservers: @@ -14517,6 +14553,24 @@ spec: - name type: object type: array + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object dnsConfig: properties: nameservers: diff --git a/docs/samples/client/kfserving_sdk_v1beta1_sample.ipynb b/docs/samples/client/kfserving_sdk_v1beta1_sample.ipynb index 830dccb5330..9f375d0d891 100644 --- a/docs/samples/client/kfserving_sdk_v1beta1_sample.ipynb +++ b/docs/samples/client/kfserving_sdk_v1beta1_sample.ipynb @@ -22,7 +22,7 @@ "metadata": {}, "outputs": [], "source": [ - "from kubernetes import client \n", + "from kubernetes import client\n", "from kfserving import KFServingClient\n", "from kfserving import constants\n", "from kfserving import utils\n", @@ -45,8 +45,8 @@ "metadata": {}, "outputs": [], "source": [ - "#namespace = utils.get_default_target_namespace()\n", - "namespace = 'kfserving-test'" + "# namespace = utils.get_default_target_namespace()\n", + "namespace = \"kfserving-test\"" ] }, { @@ -69,16 +69,21 @@ "metadata": {}, "outputs": [], "source": [ - "api_version = constants.KFSERVING_GROUP + '/' + kfserving_version\n", + "api_version = constants.KFSERVING_GROUP + \"/\" + kfserving_version\n", "\n", - "isvc = V1beta1InferenceService(api_version=api_version,\n", - " kind=constants.KFSERVING_KIND,\n", - " metadata=client.V1ObjectMeta(\n", - " name='flower-sample', namespace=namespace),\n", - " spec=V1beta1InferenceServiceSpec(\n", - " predictor=V1beta1PredictorSpec(\n", - " tensorflow=(V1beta1TFServingSpec(\n", - " storage_uri='gs://kfserving-examples/models/tensorflow/flowers'))))\n", + "isvc = V1beta1InferenceService(\n", + " api_version=api_version,\n", + " kind=constants.KFSERVING_KIND,\n", + " metadata=client.V1ObjectMeta(name=\"flower-sample\", namespace=namespace),\n", + " spec=V1beta1InferenceServiceSpec(\n", + " predictor=V1beta1PredictorSpec(\n", + " tensorflow=(\n", + " V1beta1TFServingSpec(\n", + " storage_uri=\"gs://kfserving-examples/models/tensorflow/flowers\"\n", + " )\n", + " )\n", + " )\n", + " ),\n", ")" ] }, @@ -152,7 +157,7 @@ } ], "source": [ - "KFServing.get('flower-sample', namespace=namespace, watch=True, timeout_seconds=120)" + "KFServing.get(\"flower-sample\", namespace=namespace, watch=True, timeout_seconds=120)" ] }, { @@ -223,18 +228,23 @@ } ], "source": [ - "isvc = V1beta1InferenceService(api_version=api_version,\n", - " kind=constants.KFSERVING_KIND,\n", - " metadata=client.V1ObjectMeta(\n", - " name='flower-sample', namespace=namespace),\n", - " spec=V1beta1InferenceServiceSpec(\n", - " predictor=V1beta1PredictorSpec(\n", - " canary_traffic_percent=20,\n", - " tensorflow=(V1beta1TFServingSpec(\n", - " storage_uri='gs://kfserving-examples/models/tensorflow/flowers-2'))))\n", + "isvc = V1beta1InferenceService(\n", + " api_version=api_version,\n", + " kind=constants.KFSERVING_KIND,\n", + " metadata=client.V1ObjectMeta(name=\"flower-sample\", namespace=namespace),\n", + " spec=V1beta1InferenceServiceSpec(\n", + " predictor=V1beta1PredictorSpec(\n", + " canary_traffic_percent=20,\n", + " tensorflow=(\n", + " V1beta1TFServingSpec(\n", + " storage_uri=\"gs://kfserving-examples/models/tensorflow/flowers-2\"\n", + " )\n", + " ),\n", + " )\n", + " ),\n", ")\n", "\n", - "KFServing.patch('flower-sample', isvc, namespace=namespace)" + "KFServing.patch(\"flower-sample\", isvc, namespace=namespace)" ] }, { @@ -250,7 +260,7 @@ "metadata": {}, "outputs": [], "source": [ - "KFServing.wait_isvc_ready('flower-sample', namespace=namespace)" + "KFServing.wait_isvc_ready(\"flower-sample\", namespace=namespace)" ] }, { @@ -268,7 +278,7 @@ } ], "source": [ - "KFServing.get('flower-sample', namespace=namespace, watch=True)" + "KFServing.get(\"flower-sample\", namespace=namespace, watch=True)" ] }, { @@ -313,7 +323,7 @@ } ], "source": [ - "KFServing.delete('flower-sample', namespace=namespace)" + "KFServing.delete(\"flower-sample\", namespace=namespace)" ] }, { diff --git a/docs/samples/drift-detection/alibi-detect/cifar10/cifar10_drift.ipynb b/docs/samples/drift-detection/alibi-detect/cifar10/cifar10_drift.ipynb index 7fdbf742e56..392b0f978d7 100644 --- a/docs/samples/drift-detection/alibi-detect/cifar10/cifar10_drift.ipynb +++ b/docs/samples/drift-detection/alibi-detect/cifar10/cifar10_drift.ipynb @@ -355,8 +355,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -378,7 +378,7 @@ "metadata": {}, "outputs": [], "source": [ - "#CLUSTER_IP=\"localhost:8080\"" + "# CLUSTER_IP=\"localhost:8080\"" ] }, { @@ -395,8 +395,8 @@ } ], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice -n cifar10 tfserving-cifar10 -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME_CIFAR10=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice -n cifar10 tfserving-cifar10 -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME_CIFAR10 = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME_CIFAR10)" ] }, @@ -414,8 +414,8 @@ } ], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get ksvc -n cifar10 drift-detector -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME_VAEOD=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get ksvc -n cifar10 drift-detector -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME_VAEOD = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME_VAEOD)" ] }, @@ -438,51 +438,71 @@ "import requests\n", "import json\n", "import tensorflow as tf\n", + "\n", "tf.keras.backend.clear_session()\n", "\n", "train, test = tf.keras.datasets.cifar10.load_data()\n", "X_train, y_train = train\n", "X_test, y_test = test\n", "\n", - "X_train = X_train.astype('float32') / 255\n", - "X_test = X_test.astype('float32') / 255\n", + "X_train = X_train.astype(\"float32\") / 255\n", + "X_test = X_test.astype(\"float32\") / 255\n", "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)\n", - "classes = ('plane', 'car', 'bird', 'cat',\n", - " 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')\n", + "classes = (\n", + " \"plane\",\n", + " \"car\",\n", + " \"bird\",\n", + " \"cat\",\n", + " \"deer\",\n", + " \"dog\",\n", + " \"frog\",\n", + " \"horse\",\n", + " \"ship\",\n", + " \"truck\",\n", + ")\n", + "\n", "\n", "def show(X):\n", " plt.imshow(X.reshape(32, 32, 3))\n", - " plt.axis('off')\n", + " plt.axis(\"off\")\n", " plt.show()\n", "\n", + "\n", "def predict(X):\n", - " formData = {\n", - " 'instances': X.tolist()\n", - " }\n", + " formData = {\"instances\": X.tolist()}\n", " headers = {}\n", " headers[\"Host\"] = SERVICE_HOSTNAME_CIFAR10\n", - " res = requests.post('http://'+CLUSTER_IP+'/v1/models/tfserving-cifar10:predict', json=formData, headers=headers)\n", + " res = requests.post(\n", + " \"http://\" + CLUSTER_IP + \"/v1/models/tfserving-cifar10:predict\",\n", + " json=formData,\n", + " headers=headers,\n", + " )\n", " if res.status_code == 200:\n", " j = res.json()\n", " if len(j[\"predictions\"]) == 1:\n", " return classes[np.array(j[\"predictions\"])[0].argmax()]\n", " else:\n", - " print(\"Failed with \",res.status_code)\n", + " print(\"Failed with \", res.status_code)\n", " return []\n", - " \n", + "\n", + "\n", "def drift(X):\n", - " formData = {\n", - " 'instances': X.tolist()\n", + " formData = {\"instances\": X.tolist()}\n", + " headers = {\n", + " \"ce-namespace\": \"default\",\n", + " \"ce-modelid\": \"cifar10drift\",\n", + " \"ce-type\": \"io.seldon.serving.inference.request\",\n", + " \"ce-id\": \"1234\",\n", + " \"ce-source\": \"localhost\",\n", + " \"ce-specversion\": \"1.0\",\n", " }\n", - " headers = { \"ce-namespace\": \"default\",\"ce-modelid\":\"cifar10drift\",\"ce-type\":\"io.seldon.serving.inference.request\", \\\n", - " \"ce-id\":\"1234\",\"ce-source\":\"localhost\",\"ce-specversion\":\"1.0\"}\n", - " headers[\"Host\"] = SERVICE_HOSTNAME_VAEOD \n", - " res = requests.post('http://'+CLUSTER_IP+'/', json=formData, headers=headers)\n", + " headers[\"Host\"] = SERVICE_HOSTNAME_VAEOD\n", + " res = requests.post(\"http://\" + CLUSTER_IP + \"/\", json=formData, headers=headers)\n", " if res.status_code == 200:\n", " od = res.json()\n", " return od\n", " else:\n", - " print(\"Failed with \",res.status_code)\n", + " print(\"Failed with \", res.status_code)\n", " return []" ] }, @@ -525,7 +545,7 @@ ], "source": [ "idx = 1\n", - "X = X_train[idx:idx+1]\n", + "X = X_train[idx : idx + 1]\n", "show(X)\n", "predict(X)" ] @@ -550,7 +570,7 @@ "metadata": {}, "outputs": [], "source": [ - "!kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}') " + "!kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')" ] }, { @@ -589,8 +609,9 @@ ], "source": [ "from tqdm.notebook import tqdm\n", - "for i in tqdm(range(0,5000,100)):\n", - " X = X_train[i:i+100]\n", + "\n", + "for i in tqdm(range(0, 5000, 100)):\n", + " X = X_train[i : i + 100]\n", " predict(X)" ] }, @@ -615,13 +636,13 @@ } ], "source": [ - "res=!kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}') \n", - "data= []\n", - "for i in range(0,len(res)):\n", - " if res[i] == 'Data,':\n", - " data.append(res[i+1])\n", + "res = !kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')\n", + "data = []\n", + "for i in range(0, len(res)):\n", + " if res[i] == \"Data,\":\n", + " data.append(res[i + 1])\n", "j = json.loads(json.loads(data[0]))\n", - "print(\"Drift\",j[\"data\"][\"is_drift\"]==1)" + "print(\"Drift\", j[\"data\"][\"is_drift\"] == 1)" ] }, { @@ -638,9 +659,10 @@ "outputs": [], "source": [ "from alibi_detect.datasets import fetch_cifar10c, corruption_types_cifar10c\n", - "corruption = ['motion_blur']\n", + "\n", + "corruption = [\"motion_blur\"]\n", "X_corr, y_corr = fetch_cifar10c(corruption=corruption, severity=5, return_X_y=True)\n", - "X_corr = X_corr.astype('float32') / 255" + "X_corr = X_corr.astype(\"float32\") / 255" ] }, { @@ -726,8 +748,8 @@ } ], "source": [ - "for i in tqdm(range(0,5000,100)):\n", - " X = X_corr[i:i+100]\n", + "for i in tqdm(range(0, 5000, 100)):\n", + " X = X_corr[i : i + 100]\n", " predict(X)" ] }, @@ -752,13 +774,13 @@ } ], "source": [ - "res=!kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}') \n", - "data= []\n", - "for i in range(0,len(res)):\n", - " if res[i] == 'Data,':\n", - " data.append(res[i+1])\n", + "res = !kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')\n", + "data = []\n", + "for i in range(0, len(res)):\n", + " if res[i] == \"Data,\":\n", + " data.append(res[i + 1])\n", "j = json.loads(json.loads(data[-1]))\n", - "print(\"Drift\",j[\"data\"][\"is_drift\"]==1)" + "print(\"Drift\", j[\"data\"][\"is_drift\"] == 1)" ] }, { diff --git a/docs/samples/explanation/aix/mnist/query_explain.ipynb b/docs/samples/explanation/aix/mnist/query_explain.ipynb index 478945703cb..f10e25bd744 100644 --- a/docs/samples/explanation/aix/mnist/query_explain.ipynb +++ b/docs/samples/explanation/aix/mnist/query_explain.ipynb @@ -58,7 +58,11 @@ "from keras.preprocessing import image\n", "from keras.applications.imagenet_utils import decode_predictions\n", "import time\n", - "from skimage.color import gray2rgb, rgb2gray, label2rgb # since the code wants color images" + "from skimage.color import (\n", + " gray2rgb,\n", + " rgb2gray,\n", + " label2rgb,\n", + ") # since the code wants color images" ] }, { @@ -85,18 +89,16 @@ } ], "source": [ - "print('************************************************************')\n", - "print('************************************************************')\n", - "print('************************************************************')\n", + "print(\"************************************************************\")\n", + "print(\"************************************************************\")\n", + "print(\"************************************************************\")\n", "print(\"starting query\")\n", "\n", "if len(sys.argv) < 3:\n", " raise Exception(\"No endpoint specified. \")\n", "\n", "endpoint = sys.argv[1]\n", - "headers = {\n", - " 'Host': sys.argv[2]\n", - "}\n", + "headers = {\"Host\": sys.argv[2]}\n", "test_num = 1002\n", "is_file = False\n", "if len(sys.argv) > 3:\n", @@ -118,7 +120,7 @@ " if labels[x] != 0:\n", " actual = x\n", " inputs = gray2rgb(inputs.reshape((-1, 28, 28)))\n", - " inputs = np.reshape(inputs, (28,28,3))\n", + " inputs = np.reshape(inputs, (28, 28, 3))\n", "input_image = {\"instances\": [inputs.tolist()]}" ] }, @@ -148,8 +150,8 @@ } ], "source": [ - "fig0 = (inputs[:,:,0] + 0.5)*255\n", - "f, axarr = plt.subplots(1, 1, figsize=(10,10))\n", + "fig0 = (inputs[:, :, 0] + 0.5) * 255\n", + "f, axarr = plt.subplots(1, 1, figsize=(10, 10))\n", "axarr.set_title(\"Original Image\")\n", "axarr.imshow(fig0, cmap=\"gray\")\n", "plt.show()" @@ -245,12 +247,12 @@ "masks = np.array(res_json[\"explanations\"][\"masks\"])\n", "top_labels = np.array(res_json[\"explanations\"][\"top_labels\"])\n", "\n", - "fig, m_axs = plt.subplots(2,5, figsize = (12,6))\n", + "fig, m_axs = plt.subplots(2, 5, figsize=(12, 6))\n", "for i, c_ax in enumerate(m_axs.flatten()):\n", " mask = masks[i]\n", - " c_ax.imshow(label2rgb(mask, temp, bg_label = 0), interpolation = 'nearest')\n", - " c_ax.set_title('Positive for {}\\nActual {}'.format(top_labels[i], actual))\n", - " c_ax.axis('off')\n", + " c_ax.imshow(label2rgb(mask, temp, bg_label=0), interpolation=\"nearest\")\n", + " c_ax.set_title(\"Positive for {}\\nActual {}\".format(top_labels[i], actual))\n", + " c_ax.axis(\"off\")\n", "plt.show()" ] } diff --git a/docs/samples/explanation/alibi/cifar10/cifar10_explanations.ipynb b/docs/samples/explanation/alibi/cifar10/cifar10_explanations.ipynb index 6a37482478d..1644ff8d378 100644 --- a/docs/samples/explanation/alibi/cifar10/cifar10_explanations.ipynb +++ b/docs/samples/explanation/alibi/cifar10/cifar10_explanations.ipynb @@ -56,8 +56,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -67,8 +67,8 @@ "metadata": {}, "outputs": [], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice cifar10 -n default -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice cifar10 -n default -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME)" ] }, @@ -79,7 +79,8 @@ "outputs": [], "source": [ "import sys\n", - "sys.path.append('../')\n", + "\n", + "sys.path.append(\"../\")\n", "from alibi_helper import *" ] }, diff --git a/docs/samples/explanation/alibi/income/income_explanations.ipynb b/docs/samples/explanation/alibi/income/income_explanations.ipynb index 12a49b0386a..317d7b78aec 100644 --- a/docs/samples/explanation/alibi/income/income_explanations.ipynb +++ b/docs/samples/explanation/alibi/income/income_explanations.ipynb @@ -50,8 +50,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -61,8 +61,10 @@ "metadata": {}, "outputs": [], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice income -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = (\n", + " !(kubectl get inferenceservice income -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + ")\n", + "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME)" ] }, @@ -73,9 +75,11 @@ "outputs": [], "source": [ "import sys\n", - "sys.path.append('../')\n", + "\n", + "sys.path.append(\"../\")\n", "from alibi_helper import *\n", "from alibi.datasets import fetch_adult\n", + "\n", "adult = fetch_adult()\n", "cmap = dict.fromkeys(adult.category_map.keys())\n", "for key, val in adult.category_map.items():\n", @@ -90,9 +94,17 @@ "source": [ "idxLow = 0\n", "idxHigh = 32554\n", - "for idx in [idxLow,idxHigh]:\n", - " show_row([getFeatures([adult.data[idx]], cmap)],adult)\n", - " show_prediction(predict(adult.data[idx:idx+1].tolist(),\"income\",adult,SERVICE_HOSTNAME,CLUSTER_IP))" + "for idx in [idxLow, idxHigh]:\n", + " show_row([getFeatures([adult.data[idx]], cmap)], adult)\n", + " show_prediction(\n", + " predict(\n", + " adult.data[idx : idx + 1].tolist(),\n", + " \"income\",\n", + " adult,\n", + " SERVICE_HOSTNAME,\n", + " CLUSTER_IP,\n", + " )\n", + " )" ] }, { @@ -108,7 +120,9 @@ "metadata": {}, "outputs": [], "source": [ - "exp = explain(adult.data[idxLow:idxLow+1].tolist(),\"income\",SERVICE_HOSTNAME,CLUSTER_IP)" + "exp = explain(\n", + " adult.data[idxLow : idxLow + 1].tolist(), \"income\", SERVICE_HOSTNAME, CLUSTER_IP\n", + ")" ] }, { @@ -117,7 +131,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_anchors(exp['data']['anchor'])" + "show_anchors(exp[\"data\"][\"anchor\"])" ] }, { @@ -133,8 +147,8 @@ "metadata": {}, "outputs": [], "source": [ - "show_bar([exp['data']['precision']],[''],\"Precision\")\n", - "show_bar([exp['data']['coverage']],[''],\"Coverage\")" + "show_bar([exp[\"data\"][\"precision\"]], [\"\"], \"Precision\")\n", + "show_bar([exp[\"data\"][\"coverage\"]], [\"\"], \"Coverage\")" ] }, { @@ -143,7 +157,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_feature_coverage(exp['data'])" + "show_feature_coverage(exp[\"data\"])" ] }, { @@ -152,7 +166,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_examples(exp['data'],0,adult)" + "show_examples(exp[\"data\"], 0, adult)" ] }, { @@ -163,7 +177,7 @@ }, "outputs": [], "source": [ - "show_examples(exp['data'],0,adult,False)" + "show_examples(exp[\"data\"], 0, adult, False)" ] }, { @@ -179,7 +193,9 @@ "metadata": {}, "outputs": [], "source": [ - "exp = explain(adult.data[idxHigh:idxHigh+1].tolist(),\"income\", SERVICE_HOSTNAME,CLUSTER_IP)" + "exp = explain(\n", + " adult.data[idxHigh : idxHigh + 1].tolist(), \"income\", SERVICE_HOSTNAME, CLUSTER_IP\n", + ")" ] }, { @@ -188,7 +204,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_anchors(exp['data']['anchor'])" + "show_anchors(exp[\"data\"][\"anchor\"])" ] }, { @@ -204,8 +220,8 @@ "metadata": {}, "outputs": [], "source": [ - "show_bar([exp['data']['precision']],[''],\"Precision\")\n", - "show_bar([exp['data']['coverage']],[''],\"Coverage\")" + "show_bar([exp[\"data\"][\"precision\"]], [\"\"], \"Precision\")\n", + "show_bar([exp[\"data\"][\"coverage\"]], [\"\"], \"Coverage\")" ] }, { @@ -214,7 +230,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_feature_coverage(exp['data'])" + "show_feature_coverage(exp[\"data\"])" ] }, { @@ -223,7 +239,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_examples(exp['data'],0,adult)" + "show_examples(exp[\"data\"], 0, adult)" ] }, { @@ -234,7 +250,7 @@ }, "outputs": [], "source": [ - "show_examples(exp['data'],0,adult,False)" + "show_examples(exp[\"data\"], 0, adult, False)" ] }, { diff --git a/docs/samples/explanation/alibi/moviesentiment/movie_review_explanations.ipynb b/docs/samples/explanation/alibi/moviesentiment/movie_review_explanations.ipynb index d1c6fc4e07c..1d266fdd395 100644 --- a/docs/samples/explanation/alibi/moviesentiment/movie_review_explanations.ipynb +++ b/docs/samples/explanation/alibi/moviesentiment/movie_review_explanations.ipynb @@ -38,8 +38,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -49,8 +49,8 @@ "metadata": {}, "outputs": [], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice moviesentiment -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice moviesentiment -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME)" ] }, @@ -61,7 +61,8 @@ "outputs": [], "source": [ "import sys\n", - "sys.path.append('../')\n", + "\n", + "sys.path.append(\"../\")\n", "from alibi_helper import *" ] }, @@ -72,6 +73,7 @@ "outputs": [], "source": [ "from alibi.datasets import fetch_movie_sentiment\n", + "\n", "movies = fetch_movie_sentiment()" ] }, @@ -83,9 +85,17 @@ "source": [ "idxNeg = 37\n", "idxPos = 5227\n", - "for idx in [idxNeg,idxPos]:\n", + "for idx in [idxNeg, idxPos]:\n", " print(movies.data[idx])\n", - " show_prediction(predict(movies.data[idx:idx+1],'moviesentiment',movies,SERVICE_HOSTNAME,CLUSTER_IP))" + " show_prediction(\n", + " predict(\n", + " movies.data[idx : idx + 1],\n", + " \"moviesentiment\",\n", + " movies,\n", + " SERVICE_HOSTNAME,\n", + " CLUSTER_IP,\n", + " )\n", + " )" ] }, { @@ -101,7 +111,9 @@ "metadata": {}, "outputs": [], "source": [ - "exp = explain(movies.data[idxNeg:idxNeg+1],\"moviesentiment\",SERVICE_HOSTNAME,CLUSTER_IP)" + "exp = explain(\n", + " movies.data[idxNeg : idxNeg + 1], \"moviesentiment\", SERVICE_HOSTNAME, CLUSTER_IP\n", + ")" ] }, { @@ -110,7 +122,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_anchors(exp['data']['anchor'])" + "show_anchors(exp[\"data\"][\"anchor\"])" ] }, { @@ -126,8 +138,8 @@ "metadata": {}, "outputs": [], "source": [ - "show_bar([exp['data']['precision']],[''],\"Precision\")\n", - "show_bar([exp['data']['coverage']],[''],\"Coverage\")" + "show_bar([exp[\"data\"][\"precision\"]], [\"\"], \"Precision\")\n", + "show_bar([exp[\"data\"][\"coverage\"]], [\"\"], \"Coverage\")" ] }, { @@ -136,7 +148,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_feature_coverage(exp['data'])" + "show_feature_coverage(exp[\"data\"])" ] }, { @@ -145,7 +157,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_examples(exp['data'],0,movies)" + "show_examples(exp[\"data\"], 0, movies)" ] }, { @@ -156,7 +168,7 @@ }, "outputs": [], "source": [ - "show_examples(exp['data'],0,movies,False)" + "show_examples(exp[\"data\"], 0, movies, False)" ] }, { @@ -172,7 +184,9 @@ "metadata": {}, "outputs": [], "source": [ - "exp = explain(movies.data[idxPos:idxPos+1],\"moviesentiment\",SERVICE_HOSTNAME,CLUSTER_IP)" + "exp = explain(\n", + " movies.data[idxPos : idxPos + 1], \"moviesentiment\", SERVICE_HOSTNAME, CLUSTER_IP\n", + ")" ] }, { @@ -181,7 +195,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_anchors(exp['data']['anchor'])" + "show_anchors(exp[\"data\"][\"anchor\"])" ] }, { @@ -197,8 +211,8 @@ "metadata": {}, "outputs": [], "source": [ - "show_bar([exp['data']['precision']],[''],\"Precision\")\n", - "show_bar([exp['data']['coverage']],[''],\"Coverage\")" + "show_bar([exp[\"data\"][\"precision\"]], [\"\"], \"Precision\")\n", + "show_bar([exp[\"data\"][\"coverage\"]], [\"\"], \"Coverage\")" ] }, { @@ -207,7 +221,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_feature_coverage(exp['data'])" + "show_feature_coverage(exp[\"data\"])" ] }, { @@ -216,7 +230,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_examples(exp['data'],0,movies)" + "show_examples(exp[\"data\"], 0, movies)" ] }, { @@ -227,7 +241,7 @@ }, "outputs": [], "source": [ - "show_examples(exp['data'],0,movies,False)" + "show_examples(exp[\"data\"], 0, movies, False)" ] }, { diff --git a/docs/samples/logger/basic/logger_demo.ipynb b/docs/samples/logger/basic/logger_demo.ipynb index b8739e3fb84..91c892f4ca1 100644 --- a/docs/samples/logger/basic/logger_demo.ipynb +++ b/docs/samples/logger/basic/logger_demo.ipynb @@ -63,8 +63,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -74,8 +74,8 @@ "metadata": {}, "outputs": [], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME)" ] }, @@ -86,17 +86,21 @@ "outputs": [], "source": [ "import requests\n", + "\n", + "\n", "def predict(X, name, svc_hostname, cluster_ip):\n", - " formData = {\n", - " 'instances': X\n", - " }\n", + " formData = {\"instances\": X}\n", " headers = {}\n", " headers[\"Host\"] = svc_hostname\n", - " res = requests.post('http://'+cluster_ip+'/v1/models/'+name+':predict', json=formData, headers=headers)\n", + " res = requests.post(\n", + " \"http://\" + cluster_ip + \"/v1/models/\" + name + \":predict\",\n", + " json=formData,\n", + " headers=headers,\n", + " )\n", " if res.status_code == 200:\n", " return res.json()\n", " else:\n", - " print(\"Failed with \",res.status_code)\n", + " print(\"Failed with \", res.status_code)\n", " return []" ] }, @@ -106,7 +110,7 @@ "metadata": {}, "outputs": [], "source": [ - "predict([[6.8, 2.8, 4.8, 1.4]],\"sklearn-iris\",SERVICE_HOSTNAME,CLUSTER_IP)" + "predict([[6.8, 2.8, 4.8, 1.4]], \"sklearn-iris\", SERVICE_HOSTNAME, CLUSTER_IP)" ] }, { diff --git a/docs/samples/logger/knative-eventing/logger_demo.ipynb b/docs/samples/logger/knative-eventing/logger_demo.ipynb index b8c7e9c1318..760f4305e74 100644 --- a/docs/samples/logger/knative-eventing/logger_demo.ipynb +++ b/docs/samples/logger/knative-eventing/logger_demo.ipynb @@ -113,8 +113,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -124,8 +124,8 @@ "metadata": {}, "outputs": [], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME)" ] }, @@ -136,17 +136,21 @@ "outputs": [], "source": [ "import requests\n", + "\n", + "\n", "def predict(X, name, svc_hostname, cluster_ip):\n", - " formData = {\n", - " 'instances': X\n", - " }\n", + " formData = {\"instances\": X}\n", " headers = {}\n", " headers[\"Host\"] = svc_hostname\n", - " res = requests.post('http://'+cluster_ip+'/v1/models/'+name+':predict', json=formData, headers=headers)\n", + " res = requests.post(\n", + " \"http://\" + cluster_ip + \"/v1/models/\" + name + \":predict\",\n", + " json=formData,\n", + " headers=headers,\n", + " )\n", " if res.status_code == 200:\n", " return res.json()\n", " else:\n", - " print(\"Failed with \",res.status_code)\n", + " print(\"Failed with \", res.status_code)\n", " return []" ] }, @@ -156,7 +160,7 @@ "metadata": {}, "outputs": [], "source": [ - "predict([[6.8, 2.8, 4.8, 1.4]],\"sklearn-iris\",SERVICE_HOSTNAME,CLUSTER_IP)" + "predict([[6.8, 2.8, 4.8, 1.4]], \"sklearn-iris\", SERVICE_HOSTNAME, CLUSTER_IP)" ] }, { diff --git a/docs/samples/outlier-detection/alibi-detect/cifar10/cifar10_outlier.ipynb b/docs/samples/outlier-detection/alibi-detect/cifar10/cifar10_outlier.ipynb index 7041cf7a917..e3d1c5df4b5 100644 --- a/docs/samples/outlier-detection/alibi-detect/cifar10/cifar10_outlier.ipynb +++ b/docs/samples/outlier-detection/alibi-detect/cifar10/cifar10_outlier.ipynb @@ -376,8 +376,8 @@ "metadata": {}, "outputs": [], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -389,7 +389,7 @@ }, "outputs": [], "source": [ - "CLUSTER_IP=\"localhost:8080\"" + "CLUSTER_IP = \"localhost:8080\"" ] }, { @@ -421,8 +421,8 @@ } ], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice -n cifar10 tfserving-cifar10 -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME_CIFAR10=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice -n cifar10 tfserving-cifar10 -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME_CIFAR10 = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME_CIFAR10)" ] }, @@ -442,8 +442,8 @@ } ], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get ksvc -n cifar10 vae-outlier -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME_VAEOD=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get ksvc -n cifar10 vae-outlier -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME_VAEOD = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME_VAEOD)" ] }, @@ -467,6 +467,7 @@ "import numpy as np\n", "import json\n", "import tensorflow as tf\n", + "\n", "tf.keras.backend.clear_session()\n", "\n", "from alibi_detect.od.vae import OutlierVAE\n", @@ -478,45 +479,66 @@ "X_train, y_train = train\n", "X_test, y_test = test\n", "\n", - "X_train = X_train.astype('float32') / 255\n", - "X_test = X_test.astype('float32') / 255\n", + "X_train = X_train.astype(\"float32\") / 255\n", + "X_test = X_test.astype(\"float32\") / 255\n", "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)\n", - "classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')\n", + "classes = (\n", + " \"plane\",\n", + " \"car\",\n", + " \"bird\",\n", + " \"cat\",\n", + " \"deer\",\n", + " \"dog\",\n", + " \"frog\",\n", + " \"horse\",\n", + " \"ship\",\n", + " \"truck\",\n", + ")\n", + "\n", "\n", "def show(X):\n", " plt.imshow(X.reshape(32, 32, 3))\n", - " plt.axis('off')\n", + " plt.axis(\"off\")\n", " plt.show()\n", "\n", + "\n", "def predict(X):\n", - " formData = {\n", - " 'instances': X.tolist()\n", - " }\n", + " formData = {\"instances\": X.tolist()}\n", " headers = {}\n", " headers[\"Host\"] = SERVICE_HOSTNAME_CIFAR10\n", - " res = requests.post('http://'+CLUSTER_IP+'/v1/models/tfserving-cifar10:predict', json=formData, headers=headers)\n", + " res = requests.post(\n", + " \"http://\" + CLUSTER_IP + \"/v1/models/tfserving-cifar10:predict\",\n", + " json=formData,\n", + " headers=headers,\n", + " )\n", " if res.status_code == 200:\n", " return classes[np.array(res.json()[\"predictions\"])[0].argmax()]\n", " else:\n", - " print(\"Failed with \",res.status_code)\n", + " print(\"Failed with \", res.status_code)\n", " return []\n", - " \n", + "\n", + "\n", "def outlier(X):\n", - " formData = {\n", - " 'instances': X.tolist()\n", + " formData = {\"instances\": X.tolist()}\n", + " headers = {\n", + " \"Alibi-Detect-Return-Feature-Score\": \"true\",\n", + " \"Alibi-Detect-Return-Instance-Score\": \"true\",\n", + " \"ce-namespace\": \"default\",\n", + " \"ce-modelid\": \"cifar10\",\n", + " \"ce-type\": \"io.seldon.serving.inference.request\",\n", + " \"ce-id\": \"1234\",\n", + " \"ce-source\": \"localhost\",\n", + " \"ce-specversion\": \"1.0\",\n", " }\n", - " headers = {\"Alibi-Detect-Return-Feature-Score\":\"true\",\"Alibi-Detect-Return-Instance-Score\":\"true\", \\\n", - " \"ce-namespace\": \"default\",\"ce-modelid\":\"cifar10\",\"ce-type\":\"io.seldon.serving.inference.request\", \\\n", - " \"ce-id\":\"1234\",\"ce-source\":\"localhost\",\"ce-specversion\":\"1.0\"}\n", " headers[\"Host\"] = SERVICE_HOSTNAME_VAEOD\n", - " res = requests.post('http://'+CLUSTER_IP+'/', json=formData, headers=headers)\n", + " res = requests.post(\"http://\" + CLUSTER_IP + \"/\", json=formData, headers=headers)\n", " if res.status_code == 200:\n", " od = res.json()\n", " od[\"data\"][\"feature_score\"] = np.array(od[\"data\"][\"feature_score\"])\n", " od[\"data\"][\"instance_score\"] = np.array(od[\"data\"][\"instance_score\"])\n", " return od\n", " else:\n", - " print(\"Failed with \",res.status_code)\n", + " print(\"Failed with \", res.status_code)\n", " return []" ] }, @@ -557,7 +579,7 @@ ], "source": [ "idx = 1\n", - "X = X_train[idx:idx+1]\n", + "X = X_train[idx : idx + 1]\n", "show(X)\n", "predict(X)" ] @@ -603,13 +625,13 @@ } ], "source": [ - "res=!kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}') \n", - "data= []\n", - "for i in range(0,len(res)):\n", - " if res[i] == 'Data,':\n", - " data.append(res[i+1])\n", + "res = !kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')\n", + "data = []\n", + "for i in range(0, len(res)):\n", + " if res[i] == \"Data,\":\n", + " data.append(res[i + 1])\n", "j = json.loads(json.loads(data[-1]))\n", - "print(\"Outlier\",j[\"data\"][\"is_outlier\"]==[1])" + "print(\"Outlier\", j[\"data\"][\"is_outlier\"] == [1])" ] }, { @@ -627,14 +649,16 @@ }, "outputs": [], "source": [ - "np.random.seed(0) \n", - "X_mask, mask = apply_mask(X.reshape(1, 32, 32, 3),\n", - " mask_size=(10,10),\n", - " n_masks=1,\n", - " channels=[0,1,2],\n", - " mask_type='normal',\n", - " noise_distr=(0,1),\n", - " clip_rng=(0,1))" + "np.random.seed(0)\n", + "X_mask, mask = apply_mask(\n", + " X.reshape(1, 32, 32, 3),\n", + " mask_size=(10, 10),\n", + " n_masks=1,\n", + " channels=[0, 1, 2],\n", + " mask_type=\"normal\",\n", + " noise_distr=(0, 1),\n", + " clip_rng=(0, 1),\n", + ")" ] }, { @@ -667,7 +691,7 @@ ], "source": [ "show(X_mask)\n", - "predict(X_mask)\n" + "predict(X_mask)" ] }, { @@ -711,13 +735,13 @@ } ], "source": [ - "res=!kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}') \n", - "data= []\n", - "for i in range(0,len(res)):\n", - " if res[i] == 'Data,':\n", - " data.append(res[i+1])\n", + "res = !kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')\n", + "data = []\n", + "for i in range(0, len(res)):\n", + " if res[i] == \"Data,\":\n", + " data.append(res[i + 1])\n", "j = json.loads(json.loads(data[-1]))\n", - "print(\"Outlier\",j[\"data\"][\"is_outlier\"]==[1])" + "print(\"Outlier\", j[\"data\"][\"is_outlier\"] == [1])" ] }, { @@ -746,9 +770,7 @@ } ], "source": [ - "plot_feature_outlier_image(od_preds, \n", - " X_mask, \n", - " X_recon=None)" + "plot_feature_outlier_image(od_preds, X_mask, X_recon=None)" ] }, { diff --git a/docs/samples/pipelines/kfs-pipeline.ipynb b/docs/samples/pipelines/kfs-pipeline.ipynb index 32b699d1de5..605d2ce653a 100644 --- a/docs/samples/pipelines/kfs-pipeline.ipynb +++ b/docs/samples/pipelines/kfs-pipeline.ipynb @@ -40,8 +40,8 @@ "# Note: Add the KubeFlow Pipeline endpoint below if the client is not running on the same cluster.\n", "# Example: kfp.Client('http://192.168.1.27:31380/pipeline')\n", "client = kfp.Client()\n", - "EXPERIMENT_NAME = 'KServe Experiments'\n", - "experiment = client.create_experiment(name=EXPERIMENT_NAME, namespace='anonymous')" + "EXPERIMENT_NAME = \"KServe Experiments\"\n", + "experiment = client.create_experiment(name=EXPERIMENT_NAME, namespace=\"anonymous\")" ] }, { @@ -58,30 +58,34 @@ "outputs": [], "source": [ "# kfserving_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kubeflow/kfserving/component.yaml')\n", - "kserve_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kserve/component.yaml')\n", - "\n", - "@dsl.pipeline(\n", - " name='KServe pipeline',\n", - " description='A pipeline for KServe.'\n", + "kserve_op = components.load_component_from_url(\n", + " \"https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kserve/component.yaml\"\n", ")\n", + "\n", + "\n", + "@dsl.pipeline(name=\"KServe pipeline\", description=\"A pipeline for KServe.\")\n", "def kservePipeline(\n", - " action='apply',\n", - " model_name='tensorflow-sample',\n", - " model_uri='gs://kfserving-examples/models/tensorflow/flowers',\n", - " namespace='anonymous',\n", - " framework='tensorflow'):\n", + " action=\"apply\",\n", + " model_name=\"tensorflow-sample\",\n", + " model_uri=\"gs://kfserving-examples/models/tensorflow/flowers\",\n", + " namespace=\"anonymous\",\n", + " framework=\"tensorflow\",\n", + "):\n", + "\n", + " kserve = kserve_op(\n", + " action=action,\n", + " model_name=model_name,\n", + " model_uri=model_uri,\n", + " namespace=namespace,\n", + " framework=framework,\n", + " ).set_image_pull_policy(\"Always\")\n", "\n", - " kserve = kserve_op(action = action,\n", - " model_name=model_name,\n", - " model_uri=model_uri,\n", - " namespace=namespace,\n", - " framework=framework).set_image_pull_policy('Always')\n", "\n", "# Compile pipeline\n", - "compiler.Compiler().compile(kservePipeline, 'tf-flower.tar.gz')\n", + "compiler.Compiler().compile(kservePipeline, \"tf-flower.tar.gz\")\n", "\n", "# Execute pipeline\n", - "run = client.run_pipeline(experiment.id, 'tf-flower', 'tf-flower.tar.gz')" + "run = client.run_pipeline(experiment.id, \"tf-flower\", \"tf-flower.tar.gz\")" ] }, { @@ -98,29 +102,32 @@ "outputs": [], "source": [ "# kfserving_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kubeflow/kfserving/component.yaml')\n", - "kserve_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kserve/component.yaml')\n", - "\n", - "@dsl.pipeline(\n", - " name='KServe pipeline',\n", - " description='A pipeline for KServe.'\n", + "kserve_op = components.load_component_from_url(\n", + " \"https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kserve/component.yaml\"\n", ")\n", + "\n", + "\n", + "@dsl.pipeline(name=\"KServe pipeline\", description=\"A pipeline for KServe.\")\n", "def kservePipeline(\n", - " action='apply',\n", - " model_name='max-image-segmenter',\n", - " namespace='anonymous',\n", - " custom_model_spec='{\"name\": \"image-segmenter\", \"image\": \"codait/max-image-segmenter:latest\", \"port\": \"5000\"}'\n", + " action=\"apply\",\n", + " model_name=\"max-image-segmenter\",\n", + " namespace=\"anonymous\",\n", + " custom_model_spec='{\"name\": \"image-segmenter\", \"image\": \"codait/max-image-segmenter:latest\", \"port\": \"5000\"}',\n", "):\n", "\n", - " kserve = kserve_op(action=action,\n", - " model_name=model_name,\n", - " namespace=namespace,\n", - " custom_model_spec=custom_model_spec).set_image_pull_policy('Always')\n", + " kserve = kserve_op(\n", + " action=action,\n", + " model_name=model_name,\n", + " namespace=namespace,\n", + " custom_model_spec=custom_model_spec,\n", + " ).set_image_pull_policy(\"Always\")\n", + "\n", "\n", "# Compile pipeline\n", - "compiler.Compiler().compile(kservePipeline, 'custom.tar.gz')\n", + "compiler.Compiler().compile(kservePipeline, \"custom.tar.gz\")\n", "\n", "# Execute pipeline\n", - "run = client.run_pipeline(experiment.id, 'custom-model', 'custom.tar.gz')" + "run = client.run_pipeline(experiment.id, \"custom-model\", \"custom.tar.gz\")" ] } ], diff --git a/docs/samples/v1beta1/custom/torchserve/logger/logger_demo.ipynb b/docs/samples/v1beta1/custom/torchserve/logger/logger_demo.ipynb index e23b1e4acaa..9581c8efae6 100644 --- a/docs/samples/v1beta1/custom/torchserve/logger/logger_demo.ipynb +++ b/docs/samples/v1beta1/custom/torchserve/logger/logger_demo.ipynb @@ -117,8 +117,8 @@ } ], "source": [ - "CLUSTER_IPS=!(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')\n", - "CLUSTER_IP=CLUSTER_IPS[0]\n", + "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')\n", + "CLUSTER_IP = CLUSTER_IPS[0]\n", "print(CLUSTER_IP)" ] }, @@ -136,8 +136,8 @@ } ], "source": [ - "SERVICE_HOSTNAMES=!(kubectl get inferenceservice torchserve-custom -n kfserving-test -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", - "SERVICE_HOSTNAME=SERVICE_HOSTNAMES[0]\n", + "SERVICE_HOSTNAMES = !(kubectl get inferenceservice torchserve-custom -n kfserving-test -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n", + "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n", "print(SERVICE_HOSTNAME)" ] }, @@ -241,7 +241,7 @@ } ], "source": [ - "!kubectl logs $(kubectl get pod -l serving.knative.dev/configuration=message-dumper -n default -o jsonpath='{.items[0].metadata.name}') -c user-container " + "!kubectl logs $(kubectl get pod -l serving.knative.dev/configuration=message-dumper -n default -o jsonpath='{.items[0].metadata.name}') -c user-container" ] }, { diff --git a/docs/samples/v1beta1/onnx/mosaic-onnx.ipynb b/docs/samples/v1beta1/onnx/mosaic-onnx.ipynb index 4b1658dc1c5..c0f4fe5751f 100644 --- a/docs/samples/v1beta1/onnx/mosaic-onnx.ipynb +++ b/docs/samples/v1beta1/onnx/mosaic-onnx.ipynb @@ -84,7 +84,7 @@ ], "source": [ "# preprocess image data\n", - "norm_img_data = np.array(image).astype('float32')\n", + "norm_img_data = np.array(image).astype(\"float32\")\n", "norm_img_data = np.transpose(norm_img_data, [2, 0, 1])\n", "norm_img_data = np.expand_dims(norm_img_data, axis=0)\n", "np.shape(norm_img_data)" @@ -100,10 +100,10 @@ "message_data = {}\n", "inputs = {}\n", "message_data[\"inputs\"] = []\n", - "inputs[\"name\"]=\"input1\"\n", - "inputs[\"shape\"]=norm_img_data.shape\n", - "inputs[\"datatype\"]=\"FP32\" # as the given onnx model expects float32\n", - "inputs[\"data\"]=norm_img_data.tolist()\n", + "inputs[\"name\"] = \"input1\"\n", + "inputs[\"shape\"] = norm_img_data.shape\n", + "inputs[\"datatype\"] = \"FP32\" # as the given onnx model expects float32\n", + "inputs[\"data\"] = norm_img_data.tolist()\n", "message_data[\"inputs\"].append(inputs)" ] }, @@ -123,13 +123,19 @@ "source": [ "# Call predictor\n", "\n", - "service_hostname=os.environ[\"SERVICE_HOSTNAME\"]\n", - "model_name=os.environ[\"MODEL_NAME\"]\n", - "ingress_ip=\"localhost\"\n", - "ingress_port=os.environ[\"INGRESS_PORT\"]\n", + "service_hostname = os.environ[\"SERVICE_HOSTNAME\"]\n", + "model_name = os.environ[\"MODEL_NAME\"]\n", + "ingress_ip = \"localhost\"\n", + "ingress_port = os.environ[\"INGRESS_PORT\"]\n", "predictor_url = f\"http://{ingress_ip}:{ingress_port}/v2/models/{model_name}/infer\"\n", - "request_headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'Host': service_hostname}\n", - "response = requests.post(predictor_url, headers=request_headers, data=json.dumps(message_data))\n", + "request_headers = {\n", + " \"Content-Type\": \"application/json\",\n", + " \"Accept\": \"application/json\",\n", + " \"Host\": service_hostname,\n", + "}\n", + "response = requests.post(\n", + " predictor_url, headers=request_headers, data=json.dumps(message_data)\n", + ")\n", "print(response.status_code)" ] }, @@ -140,8 +146,8 @@ "outputs": [], "source": [ "response_message = json.loads(response.text)\n", - "output1 = np.array(response_message[\"outputs\"][0]['data'], dtype=np.float32)\n", - "output1 = output1.reshape(3,224,224)" + "output1 = np.array(response_message[\"outputs\"][0][\"data\"], dtype=np.float32)\n", + "output1 = output1.reshape(3, 224, 224)" ] }, { @@ -165,7 +171,7 @@ "source": [ "# postprocess\n", "result = np.clip(output1, 0, 255)\n", - "result = result.transpose(1,2,0).astype(\"uint8\")\n", + "result = result.transpose(1, 2, 0).astype(\"uint8\")\n", "img = Image.fromarray(result)\n", "img" ] diff --git a/docs/samples/v1beta1/sklearn/v1/sklearn-mixedtype-model/sklearn-mixedtype-model.ipynb b/docs/samples/v1beta1/sklearn/v1/sklearn-mixedtype-model/sklearn-mixedtype-model.ipynb index da8f94f8a52..4cb79d0277e 100644 --- a/docs/samples/v1beta1/sklearn/v1/sklearn-mixedtype-model/sklearn-mixedtype-model.ipynb +++ b/docs/samples/v1beta1/sklearn/v1/sklearn-mixedtype-model/sklearn-mixedtype-model.ipynb @@ -36,16 +36,18 @@ "metadata": {}, "outputs": [], "source": [ - "features = [\"MSZoning\",\n", - " \"LotArea\",\n", - " \"LotShape\",\n", - " \"Utilities\",\n", - " \"YrSold\",\n", - " \"Neighborhood\",\n", - " \"OverallQual\",\n", - " \"YearBuilt\",\n", - " \"SaleType\",\n", - " \"GarageArea\"]" + "features = [\n", + " \"MSZoning\",\n", + " \"LotArea\",\n", + " \"LotShape\",\n", + " \"Utilities\",\n", + " \"YrSold\",\n", + " \"Neighborhood\",\n", + " \"OverallQual\",\n", + " \"YearBuilt\",\n", + " \"SaleType\",\n", + " \"GarageArea\",\n", + "]" ] }, { @@ -69,33 +71,33 @@ "outputs": [], "source": [ "p = Pipeline(\n", - " [\n", - " (\"dicttodf\", DictToDFTransformer()),\n", - " (\n", - " \"preprocess\",\n", - " ColumnTransformer(\n", - " [\n", - " (\n", - " \"numerical\",\n", - " make_pipeline(\n", - " SimpleImputer(strategy=\"mean\"),\n", - " StandardScaler(),\n", - " ),\n", - " sorted(numerical_features.columns),\n", + " [\n", + " (\"dicttodf\", DictToDFTransformer()),\n", + " (\n", + " \"preprocess\",\n", + " ColumnTransformer(\n", + " [\n", + " (\n", + " \"numerical\",\n", + " make_pipeline(\n", + " SimpleImputer(strategy=\"mean\"),\n", + " StandardScaler(),\n", " ),\n", - " (\n", - " \"categorical\",\n", - " make_pipeline(\n", - " SimpleImputer(strategy=\"most_frequent\"),\n", - " OneHotEncoder(handle_unknown=\"ignore\", sparse=False),\n", - " ),\n", - " sorted(categorical_features.columns),\n", + " sorted(numerical_features.columns),\n", + " ),\n", + " (\n", + " \"categorical\",\n", + " make_pipeline(\n", + " SimpleImputer(strategy=\"most_frequent\"),\n", + " OneHotEncoder(handle_unknown=\"ignore\", sparse=False),\n", " ),\n", - " ]\n", - " ),\n", + " sorted(categorical_features.columns),\n", + " ),\n", + " ]\n", " ),\n", - " (\"regressor\", SGDRegressor(random_state=666, learning_rate=\"adaptive\")),\n", - " ]\n", + " ),\n", + " (\"regressor\", SGDRegressor(random_state=666, learning_rate=\"adaptive\")),\n", + " ]\n", ")" ] }, @@ -230,7 +232,7 @@ } ], "source": [ - "sample_request = df[cols].head(1).to_dict('records')\n", + "sample_request = df[cols].head(1).to_dict(\"records\")\n", "sample_request" ] }, @@ -241,7 +243,20 @@ "metadata": {}, "outputs": [], "source": [ - "request = [{'MSZoning': 'RL', 'LotArea': 8450, 'LotShape': 'Reg', 'Utilities': 'AllPub', 'YrSold': 2008, 'Neighborhood': 'CollgCr', 'OverallQual': 7, 'YearBuilt': 2003, 'SaleType': 'WD', 'GarageArea': 548}]\n", + "request = [\n", + " {\n", + " \"MSZoning\": \"RL\",\n", + " \"LotArea\": 8450,\n", + " \"LotShape\": \"Reg\",\n", + " \"Utilities\": \"AllPub\",\n", + " \"YrSold\": 2008,\n", + " \"Neighborhood\": \"CollgCr\",\n", + " \"OverallQual\": 7,\n", + " \"YearBuilt\": 2003,\n", + " \"SaleType\": \"WD\",\n", + " \"GarageArea\": 548,\n", + " }\n", + "]\n", "response = model.predict(sample_request)" ] }, diff --git a/pkg/apis/serving/v1beta1/component.go b/pkg/apis/serving/v1beta1/component.go index 5424534adc7..bf0d937e006 100644 --- a/pkg/apis/serving/v1beta1/component.go +++ b/pkg/apis/serving/v1beta1/component.go @@ -23,6 +23,7 @@ import ( "github.com/kserve/kserve/pkg/constants" "github.com/kserve/kserve/pkg/utils" + appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -106,6 +107,10 @@ type ComponentExtensionSpec struct { // More info: http://kubernetes.io/docs/user-guide/annotations // +optional Annotations map[string]string `json:"annotations,omitempty"` + + // The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode. + // +optional + DeploymentStrategy *appsv1.DeploymentStrategy `json:"deploymentStrategy,omitempty"` } // ScaleMetric enum diff --git a/pkg/apis/serving/v1beta1/inference_service_validation.go b/pkg/apis/serving/v1beta1/inference_service_validation.go index c9c033f0945..46ad38c9406 100644 --- a/pkg/apis/serving/v1beta1/inference_service_validation.go +++ b/pkg/apis/serving/v1beta1/inference_service_validation.go @@ -224,6 +224,9 @@ func validateKPAMetrics(metric ScaleMetric) error { } func validateScalingKPACompExtension(compExtSpec *ComponentExtensionSpec) error { + if compExtSpec.DeploymentStrategy != nil { + return fmt.Errorf("customizing deploymentStrategy is only supported for raw deployment mode") + } metric := MetricConcurrency if compExtSpec.ScaleMetric != nil { metric = *compExtSpec.ScaleMetric diff --git a/pkg/apis/serving/v1beta1/inference_service_validation_test.go b/pkg/apis/serving/v1beta1/inference_service_validation_test.go index a73221c2c19..048cdd1e395 100644 --- a/pkg/apis/serving/v1beta1/inference_service_validation_test.go +++ b/pkg/apis/serving/v1beta1/inference_service_validation_test.go @@ -23,6 +23,7 @@ import ( "google.golang.org/protobuf/proto" "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -141,6 +142,18 @@ func TestRejectMultipleModelSpecs(t *testing.T) { g.Expect(warnings).Should(gomega.BeEmpty()) } +func TestCustomizeDeploymentStrategyUnsupportedForServerless(t *testing.T) { + g := gomega.NewGomegaWithT(t) + isvc := makeTestInferenceService() + isvc.Spec.Predictor.PodSpec = PodSpec{ServiceAccountName: "test"} + isvc.Spec.Predictor.DeploymentStrategy = &appsv1.DeploymentStrategy{ + Type: appsv1.RecreateDeploymentStrategyType, + } + warnings, err := isvc.ValidateCreate() + g.Expect(err).Should(gomega.MatchError("customizing deploymentStrategy is only supported for raw deployment mode")) + g.Expect(warnings).Should(gomega.BeEmpty()) +} + func TestModelSpecAndCustomOverridesIsValid(t *testing.T) { g := gomega.NewGomegaWithT(t) isvc := makeTestInferenceService() diff --git a/pkg/apis/serving/v1beta1/openapi_generated.go b/pkg/apis/serving/v1beta1/openapi_generated.go index 2148f20b689..7d82faec4ca 100644 --- a/pkg/apis/serving/v1beta1/openapi_generated.go +++ b/pkg/apis/serving/v1beta1/openapi_generated.go @@ -2263,11 +2263,17 @@ func schema_pkg_apis_serving_v1beta1_ComponentExtensionSpec(ref common.Reference }, }, }, + "deploymentStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + Ref: ref("k8s.io/api/apps/v1.DeploymentStrategy"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec"}, + "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "k8s.io/api/apps/v1.DeploymentStrategy"}, } } @@ -4603,11 +4609,17 @@ func schema_pkg_apis_serving_v1beta1_ExplainerSpec(ref common.ReferenceCallback) }, }, }, + "deploymentStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + Ref: ref("k8s.io/api/apps/v1.DeploymentStrategy"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/kserve/kserve/pkg/apis/serving/v1beta1.ARTExplainerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.AlibiExplainerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "github.com/kserve/kserve/pkg/apis/serving/v1beta1.ARTExplainerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.AlibiExplainerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "k8s.io/api/apps/v1.DeploymentStrategy", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } @@ -8325,11 +8337,17 @@ func schema_pkg_apis_serving_v1beta1_PredictorSpec(ref common.ReferenceCallback) }, }, }, + "deploymentStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + Ref: ref("k8s.io/api/apps/v1.DeploymentStrategy"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.HuggingFaceRuntimeSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LightGBMSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.ModelSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.ONNXRuntimeSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.PMMLSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.PaddleServerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.SKLearnSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.TFServingSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.TorchServeSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.TritonSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.XGBoostSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.HuggingFaceRuntimeSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LightGBMSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.ModelSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.ONNXRuntimeSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.PMMLSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.PaddleServerSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.SKLearnSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.TFServingSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.TorchServeSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.TritonSpec", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.XGBoostSpec", "k8s.io/api/apps/v1.DeploymentStrategy", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } @@ -9813,11 +9831,17 @@ func schema_pkg_apis_serving_v1beta1_TransformerSpec(ref common.ReferenceCallbac }, }, }, + "deploymentStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + Ref: ref("k8s.io/api/apps/v1.DeploymentStrategy"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "github.com/kserve/kserve/pkg/apis/serving/v1beta1.Batcher", "github.com/kserve/kserve/pkg/apis/serving/v1beta1.LoggerSpec", "k8s.io/api/apps/v1.DeploymentStrategy", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } diff --git a/pkg/apis/serving/v1beta1/swagger.json b/pkg/apis/serving/v1beta1/swagger.json index 4d1209cd7ed..cff2c8ce734 100644 --- a/pkg/apis/serving/v1beta1/swagger.json +++ b/pkg/apis/serving/v1beta1/swagger.json @@ -1186,6 +1186,10 @@ "type": "integer", "format": "int64" }, + "deploymentStrategy": { + "description": "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + "$ref": "#/definitions/k8s.io.api.apps.v1.DeploymentStrategy" + }, "labels": { "description": "Labels that will be add to the component pod. More info: http://kubernetes.io/docs/user-guide/labels", "type": "object", @@ -2277,6 +2281,10 @@ "x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge" }, + "deploymentStrategy": { + "description": "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + "$ref": "#/definitions/k8s.io.api.apps.v1.DeploymentStrategy" + }, "dnsConfig": { "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", "$ref": "#/definitions/v1.PodDNSConfig" @@ -4312,6 +4320,10 @@ "x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge" }, + "deploymentStrategy": { + "description": "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + "$ref": "#/definitions/k8s.io.api.apps.v1.DeploymentStrategy" + }, "dnsConfig": { "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", "$ref": "#/definitions/v1.PodDNSConfig" @@ -5185,6 +5197,10 @@ "x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge" }, + "deploymentStrategy": { + "description": "The deployment strategy to use to replace existing pods with new ones. Only applicable for raw deployment mode.", + "$ref": "#/definitions/k8s.io.api.apps.v1.DeploymentStrategy" + }, "dnsConfig": { "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", "$ref": "#/definitions/v1.PodDNSConfig" diff --git a/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go b/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go index 01d4bceaed9..45e0b731a0f 100644 --- a/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go @@ -23,10 +23,11 @@ package v1beta1 import ( "github.com/kserve/kserve/pkg/constants" + "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "knative.dev/pkg/apis" - "knative.dev/pkg/apis/duck/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" servingv1 "knative.dev/serving/pkg/apis/serving/v1" ) @@ -149,6 +150,11 @@ func (in *ComponentExtensionSpec) DeepCopyInto(out *ComponentExtensionSpec) { (*out)[key] = val } } + if in.DeploymentStrategy != nil { + in, out := &in.DeploymentStrategy, &out.DeploymentStrategy + *out = new(v1.DeploymentStrategy) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentExtensionSpec. @@ -188,7 +194,7 @@ func (in *ComponentStatusSpec) DeepCopyInto(out *ComponentStatusSpec) { } if in.Address != nil { in, out := &in.Address, &out.Address - *out = new(v1.Addressable) + *out = new(duckv1.Addressable) (*in).DeepCopyInto(*out) } } @@ -437,7 +443,7 @@ func (in *InferenceServiceStatus) DeepCopyInto(out *InferenceServiceStatus) { in.Status.DeepCopyInto(&out.Status) if in.Address != nil { in, out := &in.Address, &out.Address - *out = new(v1.Addressable) + *out = new(duckv1.Addressable) (*in).DeepCopyInto(*out) } if in.URL != nil { diff --git a/pkg/controller/v1beta1/inferenceservice/rawkube_controller_test.go b/pkg/controller/v1beta1/inferenceservice/rawkube_controller_test.go index a578aa87381..789983c7041 100644 --- a/pkg/controller/v1beta1/inferenceservice/rawkube_controller_test.go +++ b/pkg/controller/v1beta1/inferenceservice/rawkube_controller_test.go @@ -503,6 +503,420 @@ var _ = Describe("v1beta1 inference service controller", func() { } Expect(actualHPA.Spec).To(gomega.Equal(expectedHPA.Spec)) }) + It("Should have ingress/service/deployment/hpa created with DeploymentStrategy", func() { + By("By creating a new InferenceService with DeploymentStrategy in PredictorSpec") + // Create configmap + var configMap = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: constants.InferenceServiceConfigMapName, + Namespace: constants.KServeNamespace, + }, + Data: configs, + } + Expect(k8sClient.Create(context.TODO(), configMap)).NotTo(HaveOccurred()) + defer k8sClient.Delete(context.TODO(), configMap) + // Create ServingRuntime + servingRuntime := &v1alpha1.ServingRuntime{ + ObjectMeta: metav1.ObjectMeta{ + Name: "tf-serving-raw", + Namespace: "default", + }, + Spec: v1alpha1.ServingRuntimeSpec{ + SupportedModelFormats: []v1alpha1.SupportedModelFormat{ + { + Name: "tensorflow", + Version: proto.String("1"), + AutoSelect: proto.Bool(true), + }, + }, + ServingRuntimePodSpec: v1alpha1.ServingRuntimePodSpec{ + Containers: []v1.Container{ + { + Name: "kserve-container", + Image: "tensorflow/serving:1.14.0", + Command: []string{"/usr/bin/tensorflow_model_server"}, + Args: []string{ + "--port=9000", + "--rest_api_port=8080", + "--model_base_path=/mnt/models", + "--rest_api_timeout_in_ms=60000", + }, + Resources: defaultResource, + }, + }, + }, + Disabled: proto.Bool(false), + }, + } + k8sClient.Create(context.TODO(), servingRuntime) + defer k8sClient.Delete(context.TODO(), servingRuntime) + serviceName := "raw-foo-customized" + var expectedRequest = reconcile.Request{NamespacedName: types.NamespacedName{Name: serviceName, Namespace: "default"}} + var serviceKey = expectedRequest.NamespacedName + var storageUri = "s3://test/mnist/export" + predictorDeploymentKey := types.NamespacedName{Name: constants.PredictorServiceName(serviceKey.Name), + Namespace: serviceKey.Namespace} + var replicas int32 = 1 + var revisionHistory int32 = 10 + var progressDeadlineSeconds int32 = 600 + var gracePeriod int64 = 30 + ctx := context.Background() + isvc := &v1beta1.InferenceService{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceKey.Name, + Namespace: serviceKey.Namespace, + Annotations: map[string]string{ + "serving.kserve.io/deploymentMode": "RawDeployment", + "serving.kserve.io/autoscalerClass": "hpa", + "serving.kserve.io/metrics": "cpu", + "serving.kserve.io/targetUtilizationPercentage": "75", + }, + }, + Spec: v1beta1.InferenceServiceSpec{ + Predictor: v1beta1.PredictorSpec{ + ComponentExtensionSpec: v1beta1.ComponentExtensionSpec{ + MinReplicas: v1beta1.GetIntReference(1), + MaxReplicas: 3, + DeploymentStrategy: &appsv1.DeploymentStrategy{ + Type: appsv1.RecreateDeploymentStrategyType, + }}, + Tensorflow: &v1beta1.TFServingSpec{ + PredictorExtensionSpec: v1beta1.PredictorExtensionSpec{ + StorageURI: &storageUri, + RuntimeVersion: proto.String("1.14.0"), + Container: v1.Container{ + Name: constants.InferenceServiceContainerName, + Resources: defaultResource, + }, + }, + }, + }, + }, + } + isvc.DefaultInferenceService(nil, nil) + Expect(k8sClient.Create(ctx, isvc)).Should(Succeed()) + + inferenceService := &v1beta1.InferenceService{} + + Eventually(func() bool { + err := k8sClient.Get(ctx, serviceKey, inferenceService) + if err != nil { + return false + } + return true + }, timeout, interval).Should(BeTrue()) + + actualDeployment := &appsv1.Deployment{} + + Eventually(func() error { return k8sClient.Get(context.TODO(), predictorDeploymentKey, actualDeployment) }, timeout). + Should(Succeed()) + + expectedDeployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: predictorDeploymentKey.Name, + Namespace: predictorDeploymentKey.Namespace, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "isvc." + predictorDeploymentKey.Name, + }, + }, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Name: predictorDeploymentKey.Name, + Namespace: "default", + Labels: map[string]string{ + "app": "isvc." + predictorDeploymentKey.Name, + constants.KServiceComponentLabel: constants.Predictor.String(), + constants.InferenceServicePodLabelKey: serviceName, + }, + Annotations: map[string]string{ + constants.StorageInitializerSourceUriInternalAnnotationKey: *isvc.Spec.Predictor.Model.StorageURI, + "serving.kserve.io/deploymentMode": "RawDeployment", + "serving.kserve.io/autoscalerClass": "hpa", + "serving.kserve.io/metrics": "cpu", + "serving.kserve.io/targetUtilizationPercentage": "75", + }, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Image: "tensorflow/serving:" + + *isvc.Spec.Predictor.Model.RuntimeVersion, + Name: constants.InferenceServiceContainerName, + Command: []string{v1beta1.TensorflowEntrypointCommand}, + Args: []string{ + "--port=" + v1beta1.TensorflowServingGRPCPort, + "--rest_api_port=" + v1beta1.TensorflowServingRestPort, + "--model_base_path=" + constants.DefaultModelLocalMountPath, + "--rest_api_timeout_in_ms=60000", + }, + Resources: defaultResource, + ReadinessProbe: &v1.Probe{ + ProbeHandler: v1.ProbeHandler{ + TCPSocket: &v1.TCPSocketAction{ + Port: intstr.IntOrString{ + IntVal: 8080, + }, + }, + }, + InitialDelaySeconds: 0, + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, + FailureThreshold: 3, + }, + TerminationMessagePath: "/dev/termination-log", + TerminationMessagePolicy: "File", + ImagePullPolicy: "IfNotPresent", + }, + }, + SchedulerName: "default-scheduler", + RestartPolicy: "Always", + TerminationGracePeriodSeconds: &gracePeriod, + DNSPolicy: "ClusterFirst", + SecurityContext: &v1.PodSecurityContext{ + SELinuxOptions: nil, + WindowsOptions: nil, + RunAsUser: nil, + RunAsGroup: nil, + RunAsNonRoot: nil, + SupplementalGroups: nil, + FSGroup: nil, + Sysctls: nil, + FSGroupChangePolicy: nil, + SeccompProfile: nil, + }, + }, + }, + // This is now customized and different from defaults set via `setDefaultDeploymentSpec`. + Strategy: appsv1.DeploymentStrategy{ + Type: appsv1.RecreateDeploymentStrategyType, + }, + RevisionHistoryLimit: &revisionHistory, + ProgressDeadlineSeconds: &progressDeadlineSeconds, + }, + } + Expect(actualDeployment.Spec).To(gomega.Equal(expectedDeployment.Spec)) + + //check service + actualService := &v1.Service{} + predictorServiceKey := types.NamespacedName{Name: constants.PredictorServiceName(serviceKey.Name), + Namespace: serviceKey.Namespace} + Eventually(func() error { return k8sClient.Get(context.TODO(), predictorServiceKey, actualService) }, timeout). + Should(Succeed()) + + expectedService := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: predictorServiceKey.Name, + Namespace: predictorServiceKey.Namespace, + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{ + { + Name: constants.PredictorServiceName(serviceName), + Protocol: "TCP", + Port: 80, + TargetPort: intstr.IntOrString{Type: 0, IntVal: 8080, StrVal: ""}, + }, + }, + Type: "ClusterIP", + SessionAffinity: "None", + Selector: map[string]string{ + "app": fmt.Sprintf("isvc.%s", constants.PredictorServiceName(serviceName)), + }, + }, + } + actualService.Spec.ClusterIP = "" + actualService.Spec.ClusterIPs = nil + actualService.Spec.IPFamilies = nil + actualService.Spec.IPFamilyPolicy = nil + actualService.Spec.InternalTrafficPolicy = nil + Expect(actualService.Spec).To(gomega.Equal(expectedService.Spec)) + + //check isvc status + updatedDeployment := actualDeployment.DeepCopy() + updatedDeployment.Status.Conditions = []appsv1.DeploymentCondition{ + { + Type: appsv1.DeploymentAvailable, + Status: v1.ConditionTrue, + }, + } + Expect(k8sClient.Status().Update(context.TODO(), updatedDeployment)).NotTo(gomega.HaveOccurred()) + + //check ingress + pathType := netv1.PathTypePrefix + actualIngress := &netv1.Ingress{} + predictorIngressKey := types.NamespacedName{Name: serviceKey.Name, + Namespace: serviceKey.Namespace} + Eventually(func() error { return k8sClient.Get(context.TODO(), predictorIngressKey, actualIngress) }, timeout). + Should(Succeed()) + expectedIngress := netv1.Ingress{ + Spec: netv1.IngressSpec{ + Rules: []netv1.IngressRule{ + { + Host: "raw-foo-customized-default.example.com", + IngressRuleValue: netv1.IngressRuleValue{ + HTTP: &netv1.HTTPIngressRuleValue{ + Paths: []netv1.HTTPIngressPath{ + { + Path: "/", + PathType: &pathType, + Backend: netv1.IngressBackend{ + Service: &netv1.IngressServiceBackend{ + Name: "raw-foo-customized-predictor", + Port: netv1.ServiceBackendPort{ + Number: 80, + }, + }, + }, + }, + }, + }, + }, + }, + { + Host: "raw-foo-customized-predictor-default.example.com", + IngressRuleValue: netv1.IngressRuleValue{ + HTTP: &netv1.HTTPIngressRuleValue{ + Paths: []netv1.HTTPIngressPath{ + { + Path: "/", + PathType: &pathType, + Backend: netv1.IngressBackend{ + Service: &netv1.IngressServiceBackend{ + Name: "raw-foo-customized-predictor", + Port: netv1.ServiceBackendPort{ + Number: 80, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + Expect(actualIngress.Spec).To(gomega.Equal(expectedIngress.Spec)) + // verify if InferenceService status is updated + expectedIsvcStatus := v1beta1.InferenceServiceStatus{ + Status: duckv1.Status{ + Conditions: duckv1.Conditions{ + { + Type: v1beta1.IngressReady, + Status: "True", + }, + { + Type: v1beta1.PredictorReady, + Status: "True", + }, + { + Type: apis.ConditionReady, + Status: "True", + }, + }, + }, + URL: &apis.URL{ + Scheme: "http", + Host: "raw-foo-customized-default.example.com", + }, + Address: &duckv1.Addressable{ + URL: &apis.URL{ + Scheme: "http", + Host: fmt.Sprintf("%s-predictor.%s.svc.cluster.local", serviceKey.Name, serviceKey.Namespace), + }, + }, + Components: map[v1beta1.ComponentType]v1beta1.ComponentStatusSpec{ + v1beta1.PredictorComponent: { + LatestCreatedRevision: "", + URL: &apis.URL{ + Scheme: "http", + Host: "raw-foo-customized-predictor-default.example.com", + }, + }, + }, + ModelStatus: v1beta1.ModelStatus{ + TransitionStatus: "InProgress", + ModelRevisionStates: &v1beta1.ModelRevisionStates{TargetModelState: "Pending"}, + }, + } + Eventually(func() string { + isvc := &v1beta1.InferenceService{} + if err := k8sClient.Get(context.TODO(), serviceKey, isvc); err != nil { + return err.Error() + } + return cmp.Diff(&expectedIsvcStatus, &isvc.Status, cmpopts.IgnoreTypes(apis.VolatileTime{})) + }, timeout).Should(gomega.BeEmpty()) + + //check HPA + var minReplicas int32 = 1 + var maxReplicas int32 = 3 + var cpuUtilization int32 = 75 + var stabilizationWindowSeconds int32 = 0 + selectPolicy := autoscalingv2.MaxChangePolicySelect + actualHPA := &autoscalingv2.HorizontalPodAutoscaler{} + predictorHPAKey := types.NamespacedName{Name: constants.PredictorServiceName(serviceKey.Name), + Namespace: serviceKey.Namespace} + Eventually(func() error { return k8sClient.Get(context.TODO(), predictorHPAKey, actualHPA) }, timeout). + Should(Succeed()) + expectedHPA := &autoscalingv2.HorizontalPodAutoscaler{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ + APIVersion: "apps/v1", + Kind: "Deployment", + Name: constants.PredictorServiceName(serviceKey.Name), + }, + MinReplicas: &minReplicas, + MaxReplicas: maxReplicas, + Metrics: []autoscalingv2.MetricSpec{ + { + Type: autoscalingv2.ResourceMetricSourceType, + Resource: &autoscalingv2.ResourceMetricSource{ + Name: v1.ResourceCPU, + Target: autoscalingv2.MetricTarget{ + Type: "Utilization", + AverageUtilization: &cpuUtilization, + }, + }, + }, + }, + Behavior: &autoscalingv2.HorizontalPodAutoscalerBehavior{ + ScaleUp: &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &stabilizationWindowSeconds, + SelectPolicy: &selectPolicy, + Policies: []autoscalingv2.HPAScalingPolicy{ + { + Type: "Pods", + Value: 4, + PeriodSeconds: 15, + }, + { + Type: "Percent", + Value: 100, + PeriodSeconds: 15, + }, + }, + }, + ScaleDown: &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: nil, + SelectPolicy: &selectPolicy, + Policies: []autoscalingv2.HPAScalingPolicy{ + { + Type: "Percent", + Value: 100, + PeriodSeconds: 15, + }, + }, + }, + }, + }, + } + Expect(actualHPA.Spec).To(gomega.Equal(expectedHPA.Spec)) + }) It("Should have ingress/service/deployment created", func() { By("By creating a new InferenceService with AutoscalerClassExternal") // Create configmap diff --git a/pkg/controller/v1beta1/inferenceservice/reconcilers/deployment/deployment_reconciler.go b/pkg/controller/v1beta1/inferenceservice/reconcilers/deployment/deployment_reconciler.go index 92a8f0f972c..58efa664c37 100644 --- a/pkg/controller/v1beta1/inferenceservice/reconcilers/deployment/deployment_reconciler.go +++ b/pkg/controller/v1beta1/inferenceservice/reconcilers/deployment/deployment_reconciler.go @@ -77,6 +77,9 @@ func createRawDeployment(componentMeta metav1.ObjectMeta, }, }, } + if componentExt.DeploymentStrategy != nil { + deployment.Spec.Strategy = *componentExt.DeploymentStrategy + } setDefaultDeploymentSpec(&deployment.Spec) return deployment } @@ -182,7 +185,7 @@ func setDefaultDeploymentSpec(spec *appsv1.DeploymentSpec) { if spec.Strategy.Type == "" { spec.Strategy.Type = appsv1.RollingUpdateDeploymentStrategyType } - if spec.Strategy.RollingUpdate == nil { + if spec.Strategy.Type == appsv1.RollingUpdateDeploymentStrategyType && spec.Strategy.RollingUpdate == nil { spec.Strategy.RollingUpdate = &appsv1.RollingUpdateDeployment{ MaxUnavailable: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, MaxSurge: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, diff --git a/python/kserve/docs/V1beta1ComponentExtensionSpec.md b/python/kserve/docs/V1beta1ComponentExtensionSpec.md index a44bc4bcc85..3eeb1f170ec 100644 --- a/python/kserve/docs/V1beta1ComponentExtensionSpec.md +++ b/python/kserve/docs/V1beta1ComponentExtensionSpec.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **batcher** | [**V1beta1Batcher**](V1beta1Batcher.md) | | [optional] **canary_traffic_percent** | **int** | CanaryTrafficPercent defines the traffic split percentage between the candidate revision and the last ready revision | [optional] **container_concurrency** | **int** | ContainerConcurrency specifies how many requests can be processed concurrently, this sets the hard limit of the container concurrency(https://knative.dev/docs/serving/autoscaling/concurrency). | [optional] +**deployment_strategy** | [**K8sIoApiAppsV1DeploymentStrategy**](K8sIoApiAppsV1DeploymentStrategy.md) | | [optional] **labels** | **dict(str, str)** | Labels that will be add to the component pod. More info: http://kubernetes.io/docs/user-guide/labels | [optional] **logger** | [**V1beta1LoggerSpec**](V1beta1LoggerSpec.md) | | [optional] **max_replicas** | **int** | Maximum number of replicas for autoscaling. | [optional] diff --git a/python/kserve/docs/V1beta1ExplainerSpec.md b/python/kserve/docs/V1beta1ExplainerSpec.md index 45809ed85e9..c6607b2c955 100644 --- a/python/kserve/docs/V1beta1ExplainerSpec.md +++ b/python/kserve/docs/V1beta1ExplainerSpec.md @@ -14,6 +14,7 @@ Name | Type | Description | Notes **canary_traffic_percent** | **int** | CanaryTrafficPercent defines the traffic split percentage between the candidate revision and the last ready revision | [optional] **container_concurrency** | **int** | ContainerConcurrency specifies how many requests can be processed concurrently, this sets the hard limit of the container concurrency(https://knative.dev/docs/serving/autoscaling/concurrency). | [optional] **containers** | [**list[V1Container]**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Container.md) | List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. | [optional] +**deployment_strategy** | [**K8sIoApiAppsV1DeploymentStrategy**](K8sIoApiAppsV1DeploymentStrategy.md) | | [optional] **dns_config** | [**V1PodDNSConfig**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1PodDNSConfig.md) | | [optional] **dns_policy** | **str** | Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. | [optional] **enable_service_links** | **bool** | EnableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. Optional: Defaults to true. | [optional] diff --git a/python/kserve/docs/V1beta1PredictorSpec.md b/python/kserve/docs/V1beta1PredictorSpec.md index 21af0d1d9a6..74ef7b385dd 100644 --- a/python/kserve/docs/V1beta1PredictorSpec.md +++ b/python/kserve/docs/V1beta1PredictorSpec.md @@ -12,6 +12,7 @@ Name | Type | Description | Notes **canary_traffic_percent** | **int** | CanaryTrafficPercent defines the traffic split percentage between the candidate revision and the last ready revision | [optional] **container_concurrency** | **int** | ContainerConcurrency specifies how many requests can be processed concurrently, this sets the hard limit of the container concurrency(https://knative.dev/docs/serving/autoscaling/concurrency). | [optional] **containers** | [**list[V1Container]**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Container.md) | List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. | [optional] +**deployment_strategy** | [**K8sIoApiAppsV1DeploymentStrategy**](K8sIoApiAppsV1DeploymentStrategy.md) | | [optional] **dns_config** | [**V1PodDNSConfig**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1PodDNSConfig.md) | | [optional] **dns_policy** | **str** | Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. | [optional] **enable_service_links** | **bool** | EnableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. Optional: Defaults to true. | [optional] diff --git a/python/kserve/docs/V1beta1TransformerSpec.md b/python/kserve/docs/V1beta1TransformerSpec.md index 47fa9aa151e..9988cb90633 100644 --- a/python/kserve/docs/V1beta1TransformerSpec.md +++ b/python/kserve/docs/V1beta1TransformerSpec.md @@ -12,6 +12,7 @@ Name | Type | Description | Notes **canary_traffic_percent** | **int** | CanaryTrafficPercent defines the traffic split percentage between the candidate revision and the last ready revision | [optional] **container_concurrency** | **int** | ContainerConcurrency specifies how many requests can be processed concurrently, this sets the hard limit of the container concurrency(https://knative.dev/docs/serving/autoscaling/concurrency). | [optional] **containers** | [**list[V1Container]**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Container.md) | List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. | [optional] +**deployment_strategy** | [**K8sIoApiAppsV1DeploymentStrategy**](K8sIoApiAppsV1DeploymentStrategy.md) | | [optional] **dns_config** | [**V1PodDNSConfig**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1PodDNSConfig.md) | | [optional] **dns_policy** | **str** | Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. | [optional] **enable_service_links** | **bool** | EnableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. Optional: Defaults to true. | [optional] diff --git a/python/kserve/kserve/models/v1beta1_component_extension_spec.py b/python/kserve/kserve/models/v1beta1_component_extension_spec.py index cd78e0264e0..b92940ba653 100644 --- a/python/kserve/kserve/models/v1beta1_component_extension_spec.py +++ b/python/kserve/kserve/models/v1beta1_component_extension_spec.py @@ -51,6 +51,7 @@ class V1beta1ComponentExtensionSpec(object): 'batcher': 'V1beta1Batcher', 'canary_traffic_percent': 'int', 'container_concurrency': 'int', + 'deployment_strategy': 'K8sIoApiAppsV1DeploymentStrategy', 'labels': 'dict(str, str)', 'logger': 'V1beta1LoggerSpec', 'max_replicas': 'int', @@ -65,6 +66,7 @@ class V1beta1ComponentExtensionSpec(object): 'batcher': 'batcher', 'canary_traffic_percent': 'canaryTrafficPercent', 'container_concurrency': 'containerConcurrency', + 'deployment_strategy': 'deploymentStrategy', 'labels': 'labels', 'logger': 'logger', 'max_replicas': 'maxReplicas', @@ -74,7 +76,7 @@ class V1beta1ComponentExtensionSpec(object): 'timeout': 'timeout' } - def __init__(self, annotations=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, labels=None, logger=None, max_replicas=None, min_replicas=None, scale_metric=None, scale_target=None, timeout=None, local_vars_configuration=None): # noqa: E501 + def __init__(self, annotations=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, deployment_strategy=None, labels=None, logger=None, max_replicas=None, min_replicas=None, scale_metric=None, scale_target=None, timeout=None, local_vars_configuration=None): # noqa: E501 """V1beta1ComponentExtensionSpec - a model defined in OpenAPI""" # noqa: E501 if local_vars_configuration is None: local_vars_configuration = Configuration() @@ -84,6 +86,7 @@ def __init__(self, annotations=None, batcher=None, canary_traffic_percent=None, self._batcher = None self._canary_traffic_percent = None self._container_concurrency = None + self._deployment_strategy = None self._labels = None self._logger = None self._max_replicas = None @@ -101,6 +104,8 @@ def __init__(self, annotations=None, batcher=None, canary_traffic_percent=None, self.canary_traffic_percent = canary_traffic_percent if container_concurrency is not None: self.container_concurrency = container_concurrency + if deployment_strategy is not None: + self.deployment_strategy = deployment_strategy if labels is not None: self.labels = labels if logger is not None: @@ -206,6 +211,27 @@ def container_concurrency(self, container_concurrency): self._container_concurrency = container_concurrency + @property + def deployment_strategy(self): + """Gets the deployment_strategy of this V1beta1ComponentExtensionSpec. # noqa: E501 + + + :return: The deployment_strategy of this V1beta1ComponentExtensionSpec. # noqa: E501 + :rtype: K8sIoApiAppsV1DeploymentStrategy + """ + return self._deployment_strategy + + @deployment_strategy.setter + def deployment_strategy(self, deployment_strategy): + """Sets the deployment_strategy of this V1beta1ComponentExtensionSpec. + + + :param deployment_strategy: The deployment_strategy of this V1beta1ComponentExtensionSpec. # noqa: E501 + :type: K8sIoApiAppsV1DeploymentStrategy + """ + + self._deployment_strategy = deployment_strategy + @property def labels(self): """Gets the labels of this V1beta1ComponentExtensionSpec. # noqa: E501 diff --git a/python/kserve/kserve/models/v1beta1_explainer_spec.py b/python/kserve/kserve/models/v1beta1_explainer_spec.py index fdab1803db5..dec7b98db87 100644 --- a/python/kserve/kserve/models/v1beta1_explainer_spec.py +++ b/python/kserve/kserve/models/v1beta1_explainer_spec.py @@ -57,6 +57,7 @@ class V1beta1ExplainerSpec(object): 'canary_traffic_percent': 'int', 'container_concurrency': 'int', 'containers': 'list[V1Container]', + 'deployment_strategy': 'K8sIoApiAppsV1DeploymentStrategy', 'dns_config': 'V1PodDNSConfig', 'dns_policy': 'str', 'enable_service_links': 'bool', @@ -112,6 +113,7 @@ class V1beta1ExplainerSpec(object): 'canary_traffic_percent': 'canaryTrafficPercent', 'container_concurrency': 'containerConcurrency', 'containers': 'containers', + 'deployment_strategy': 'deploymentStrategy', 'dns_config': 'dnsConfig', 'dns_policy': 'dnsPolicy', 'enable_service_links': 'enableServiceLinks', @@ -156,7 +158,7 @@ class V1beta1ExplainerSpec(object): 'volumes': 'volumes' } - def __init__(self, active_deadline_seconds=None, affinity=None, alibi=None, annotations=None, art=None, automount_service_account_token=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, containers=None, dns_config=None, dns_policy=None, enable_service_links=None, ephemeral_containers=None, host_aliases=None, host_ipc=None, host_network=None, host_pid=None, host_users=None, hostname=None, image_pull_secrets=None, init_containers=None, labels=None, logger=None, max_replicas=None, min_replicas=None, node_name=None, node_selector=None, os=None, overhead=None, preemption_policy=None, priority=None, priority_class_name=None, readiness_gates=None, resource_claims=None, restart_policy=None, runtime_class_name=None, scale_metric=None, scale_target=None, scheduler_name=None, scheduling_gates=None, security_context=None, service_account=None, service_account_name=None, set_hostname_as_fqdn=None, share_process_namespace=None, subdomain=None, termination_grace_period_seconds=None, timeout=None, tolerations=None, topology_spread_constraints=None, volumes=None, local_vars_configuration=None): # noqa: E501 + def __init__(self, active_deadline_seconds=None, affinity=None, alibi=None, annotations=None, art=None, automount_service_account_token=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, containers=None, deployment_strategy=None, dns_config=None, dns_policy=None, enable_service_links=None, ephemeral_containers=None, host_aliases=None, host_ipc=None, host_network=None, host_pid=None, host_users=None, hostname=None, image_pull_secrets=None, init_containers=None, labels=None, logger=None, max_replicas=None, min_replicas=None, node_name=None, node_selector=None, os=None, overhead=None, preemption_policy=None, priority=None, priority_class_name=None, readiness_gates=None, resource_claims=None, restart_policy=None, runtime_class_name=None, scale_metric=None, scale_target=None, scheduler_name=None, scheduling_gates=None, security_context=None, service_account=None, service_account_name=None, set_hostname_as_fqdn=None, share_process_namespace=None, subdomain=None, termination_grace_period_seconds=None, timeout=None, tolerations=None, topology_spread_constraints=None, volumes=None, local_vars_configuration=None): # noqa: E501 """V1beta1ExplainerSpec - a model defined in OpenAPI""" # noqa: E501 if local_vars_configuration is None: local_vars_configuration = Configuration() @@ -172,6 +174,7 @@ def __init__(self, active_deadline_seconds=None, affinity=None, alibi=None, anno self._canary_traffic_percent = None self._container_concurrency = None self._containers = None + self._deployment_strategy = None self._dns_config = None self._dns_policy = None self._enable_service_links = None @@ -236,6 +239,8 @@ def __init__(self, active_deadline_seconds=None, affinity=None, alibi=None, anno self.container_concurrency = container_concurrency if containers is not None: self.containers = containers + if deployment_strategy is not None: + self.deployment_strategy = deployment_strategy if dns_config is not None: self.dns_config = dns_config if dns_policy is not None: @@ -543,6 +548,27 @@ def containers(self, containers): self._containers = containers + @property + def deployment_strategy(self): + """Gets the deployment_strategy of this V1beta1ExplainerSpec. # noqa: E501 + + + :return: The deployment_strategy of this V1beta1ExplainerSpec. # noqa: E501 + :rtype: K8sIoApiAppsV1DeploymentStrategy + """ + return self._deployment_strategy + + @deployment_strategy.setter + def deployment_strategy(self, deployment_strategy): + """Sets the deployment_strategy of this V1beta1ExplainerSpec. + + + :param deployment_strategy: The deployment_strategy of this V1beta1ExplainerSpec. # noqa: E501 + :type: K8sIoApiAppsV1DeploymentStrategy + """ + + self._deployment_strategy = deployment_strategy + @property def dns_config(self): """Gets the dns_config of this V1beta1ExplainerSpec. # noqa: E501 diff --git a/python/kserve/kserve/models/v1beta1_predictor_spec.py b/python/kserve/kserve/models/v1beta1_predictor_spec.py index 0c7d531dcdf..8d08b873a5a 100644 --- a/python/kserve/kserve/models/v1beta1_predictor_spec.py +++ b/python/kserve/kserve/models/v1beta1_predictor_spec.py @@ -55,6 +55,7 @@ class V1beta1PredictorSpec(object): 'canary_traffic_percent': 'int', 'container_concurrency': 'int', 'containers': 'list[V1Container]', + 'deployment_strategy': 'K8sIoApiAppsV1DeploymentStrategy', 'dns_config': 'V1PodDNSConfig', 'dns_policy': 'str', 'enable_service_links': 'bool', @@ -119,6 +120,7 @@ class V1beta1PredictorSpec(object): 'canary_traffic_percent': 'canaryTrafficPercent', 'container_concurrency': 'containerConcurrency', 'containers': 'containers', + 'deployment_strategy': 'deploymentStrategy', 'dns_config': 'dnsConfig', 'dns_policy': 'dnsPolicy', 'enable_service_links': 'enableServiceLinks', @@ -174,7 +176,7 @@ class V1beta1PredictorSpec(object): 'xgboost': 'xgboost' } - def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None, automount_service_account_token=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, containers=None, dns_config=None, dns_policy=None, enable_service_links=None, ephemeral_containers=None, host_aliases=None, host_ipc=None, host_network=None, host_pid=None, host_users=None, hostname=None, huggingface=None, image_pull_secrets=None, init_containers=None, labels=None, lightgbm=None, logger=None, max_replicas=None, min_replicas=None, model=None, node_name=None, node_selector=None, onnx=None, os=None, overhead=None, paddle=None, pmml=None, preemption_policy=None, priority=None, priority_class_name=None, pytorch=None, readiness_gates=None, resource_claims=None, restart_policy=None, runtime_class_name=None, scale_metric=None, scale_target=None, scheduler_name=None, scheduling_gates=None, security_context=None, service_account=None, service_account_name=None, set_hostname_as_fqdn=None, share_process_namespace=None, sklearn=None, subdomain=None, tensorflow=None, termination_grace_period_seconds=None, timeout=None, tolerations=None, topology_spread_constraints=None, triton=None, volumes=None, xgboost=None, local_vars_configuration=None): # noqa: E501 + def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None, automount_service_account_token=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, containers=None, deployment_strategy=None, dns_config=None, dns_policy=None, enable_service_links=None, ephemeral_containers=None, host_aliases=None, host_ipc=None, host_network=None, host_pid=None, host_users=None, hostname=None, huggingface=None, image_pull_secrets=None, init_containers=None, labels=None, lightgbm=None, logger=None, max_replicas=None, min_replicas=None, model=None, node_name=None, node_selector=None, onnx=None, os=None, overhead=None, paddle=None, pmml=None, preemption_policy=None, priority=None, priority_class_name=None, pytorch=None, readiness_gates=None, resource_claims=None, restart_policy=None, runtime_class_name=None, scale_metric=None, scale_target=None, scheduler_name=None, scheduling_gates=None, security_context=None, service_account=None, service_account_name=None, set_hostname_as_fqdn=None, share_process_namespace=None, sklearn=None, subdomain=None, tensorflow=None, termination_grace_period_seconds=None, timeout=None, tolerations=None, topology_spread_constraints=None, triton=None, volumes=None, xgboost=None, local_vars_configuration=None): # noqa: E501 """V1beta1PredictorSpec - a model defined in OpenAPI""" # noqa: E501 if local_vars_configuration is None: local_vars_configuration = Configuration() @@ -188,6 +190,7 @@ def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None self._canary_traffic_percent = None self._container_concurrency = None self._containers = None + self._deployment_strategy = None self._dns_config = None self._dns_policy = None self._enable_service_links = None @@ -259,6 +262,8 @@ def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None self.container_concurrency = container_concurrency if containers is not None: self.containers = containers + if deployment_strategy is not None: + self.deployment_strategy = deployment_strategy if dns_config is not None: self.dns_config = dns_config if dns_policy is not None: @@ -546,6 +551,27 @@ def containers(self, containers): self._containers = containers + @property + def deployment_strategy(self): + """Gets the deployment_strategy of this V1beta1PredictorSpec. # noqa: E501 + + + :return: The deployment_strategy of this V1beta1PredictorSpec. # noqa: E501 + :rtype: K8sIoApiAppsV1DeploymentStrategy + """ + return self._deployment_strategy + + @deployment_strategy.setter + def deployment_strategy(self, deployment_strategy): + """Sets the deployment_strategy of this V1beta1PredictorSpec. + + + :param deployment_strategy: The deployment_strategy of this V1beta1PredictorSpec. # noqa: E501 + :type: K8sIoApiAppsV1DeploymentStrategy + """ + + self._deployment_strategy = deployment_strategy + @property def dns_config(self): """Gets the dns_config of this V1beta1PredictorSpec. # noqa: E501 diff --git a/python/kserve/kserve/models/v1beta1_transformer_spec.py b/python/kserve/kserve/models/v1beta1_transformer_spec.py index ccd878d7cdf..c6aa8428f68 100644 --- a/python/kserve/kserve/models/v1beta1_transformer_spec.py +++ b/python/kserve/kserve/models/v1beta1_transformer_spec.py @@ -55,6 +55,7 @@ class V1beta1TransformerSpec(object): 'canary_traffic_percent': 'int', 'container_concurrency': 'int', 'containers': 'list[V1Container]', + 'deployment_strategy': 'K8sIoApiAppsV1DeploymentStrategy', 'dns_config': 'V1PodDNSConfig', 'dns_policy': 'str', 'enable_service_links': 'bool', @@ -108,6 +109,7 @@ class V1beta1TransformerSpec(object): 'canary_traffic_percent': 'canaryTrafficPercent', 'container_concurrency': 'containerConcurrency', 'containers': 'containers', + 'deployment_strategy': 'deploymentStrategy', 'dns_config': 'dnsConfig', 'dns_policy': 'dnsPolicy', 'enable_service_links': 'enableServiceLinks', @@ -152,7 +154,7 @@ class V1beta1TransformerSpec(object): 'volumes': 'volumes' } - def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None, automount_service_account_token=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, containers=None, dns_config=None, dns_policy=None, enable_service_links=None, ephemeral_containers=None, host_aliases=None, host_ipc=None, host_network=None, host_pid=None, host_users=None, hostname=None, image_pull_secrets=None, init_containers=None, labels=None, logger=None, max_replicas=None, min_replicas=None, node_name=None, node_selector=None, os=None, overhead=None, preemption_policy=None, priority=None, priority_class_name=None, readiness_gates=None, resource_claims=None, restart_policy=None, runtime_class_name=None, scale_metric=None, scale_target=None, scheduler_name=None, scheduling_gates=None, security_context=None, service_account=None, service_account_name=None, set_hostname_as_fqdn=None, share_process_namespace=None, subdomain=None, termination_grace_period_seconds=None, timeout=None, tolerations=None, topology_spread_constraints=None, volumes=None, local_vars_configuration=None): # noqa: E501 + def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None, automount_service_account_token=None, batcher=None, canary_traffic_percent=None, container_concurrency=None, containers=None, deployment_strategy=None, dns_config=None, dns_policy=None, enable_service_links=None, ephemeral_containers=None, host_aliases=None, host_ipc=None, host_network=None, host_pid=None, host_users=None, hostname=None, image_pull_secrets=None, init_containers=None, labels=None, logger=None, max_replicas=None, min_replicas=None, node_name=None, node_selector=None, os=None, overhead=None, preemption_policy=None, priority=None, priority_class_name=None, readiness_gates=None, resource_claims=None, restart_policy=None, runtime_class_name=None, scale_metric=None, scale_target=None, scheduler_name=None, scheduling_gates=None, security_context=None, service_account=None, service_account_name=None, set_hostname_as_fqdn=None, share_process_namespace=None, subdomain=None, termination_grace_period_seconds=None, timeout=None, tolerations=None, topology_spread_constraints=None, volumes=None, local_vars_configuration=None): # noqa: E501 """V1beta1TransformerSpec - a model defined in OpenAPI""" # noqa: E501 if local_vars_configuration is None: local_vars_configuration = Configuration() @@ -166,6 +168,7 @@ def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None self._canary_traffic_percent = None self._container_concurrency = None self._containers = None + self._deployment_strategy = None self._dns_config = None self._dns_policy = None self._enable_service_links = None @@ -226,6 +229,8 @@ def __init__(self, active_deadline_seconds=None, affinity=None, annotations=None self.container_concurrency = container_concurrency if containers is not None: self.containers = containers + if deployment_strategy is not None: + self.deployment_strategy = deployment_strategy if dns_config is not None: self.dns_config = dns_config if dns_policy is not None: @@ -491,6 +496,27 @@ def containers(self, containers): self._containers = containers + @property + def deployment_strategy(self): + """Gets the deployment_strategy of this V1beta1TransformerSpec. # noqa: E501 + + + :return: The deployment_strategy of this V1beta1TransformerSpec. # noqa: E501 + :rtype: K8sIoApiAppsV1DeploymentStrategy + """ + return self._deployment_strategy + + @deployment_strategy.setter + def deployment_strategy(self, deployment_strategy): + """Sets the deployment_strategy of this V1beta1TransformerSpec. + + + :param deployment_strategy: The deployment_strategy of this V1beta1TransformerSpec. # noqa: E501 + :type: K8sIoApiAppsV1DeploymentStrategy + """ + + self._deployment_strategy = deployment_strategy + @property def dns_config(self): """Gets the dns_config of this V1beta1TransformerSpec. # noqa: E501 diff --git a/test/crds/serving.kserve.io_inferenceservices.yaml b/test/crds/serving.kserve.io_inferenceservices.yaml index 331eda7e785..c267020493b 100644 --- a/test/crds/serving.kserve.io_inferenceservices.yaml +++ b/test/crds/serving.kserve.io_inferenceservices.yaml @@ -1,1898 +1,3 @@ -#apiVersion: apiextensions.k8s.io/v1 -#kind: CustomResourceDefinition -#metadata: -# annotations: -# controller-gen.kubebuilder.io/version: v0.12.0 -# name: clusterservingruntimes.serving.kserve.io -#spec: -# group: serving.kserve.io -# names: -# kind: ClusterServingRuntime -# listKind: ClusterServingRuntimeList -# plural: clusterservingruntimes -# singular: clusterservingruntime -# scope: Cluster -# versions: -# - additionalPrinterColumns: -# - jsonPath: .spec.disabled -# name: Disabled -# type: boolean -# - jsonPath: .spec.supportedModelFormats[*].name -# name: ModelType -# type: string -# - jsonPath: .spec.containers[*].name -# name: Containers -# type: string -# - jsonPath: .metadata.creationTimestamp -# name: Age -# type: date -# name: v1alpha1 -# schema: -# openAPIV3Schema: -# properties: -# apiVersion: -# type: string -# kind: -# type: string -# metadata: -# type: object -# spec: -# properties: -# affinity: -# properties: -# nodeAffinity: -# properties: -# preferredDuringSchedulingIgnoredDuringExecution: -# items: -# properties: -# preference: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchFields: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# type: object -# x-kubernetes-map-type: atomic -# weight: -# format: int32 -# type: integer -# required: -# - preference -# - weight -# type: object -# type: array -# requiredDuringSchedulingIgnoredDuringExecution: -# properties: -# nodeSelectorTerms: -# items: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchFields: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# type: object -# x-kubernetes-map-type: atomic -# type: array -# required: -# - nodeSelectorTerms -# type: object -# x-kubernetes-map-type: atomic -# type: object -# podAffinity: -# properties: -# preferredDuringSchedulingIgnoredDuringExecution: -# items: -# properties: -# podAffinityTerm: -# properties: -# labelSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaceSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaces: -# items: -# type: string -# type: array -# topologyKey: -# type: string -# required: -# - topologyKey -# type: object -# weight: -# format: int32 -# type: integer -# required: -# - podAffinityTerm -# - weight -# type: object -# type: array -# requiredDuringSchedulingIgnoredDuringExecution: -# items: -# properties: -# labelSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaceSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaces: -# items: -# type: string -# type: array -# topologyKey: -# type: string -# required: -# - topologyKey -# type: object -# type: array -# type: object -# podAntiAffinity: -# properties: -# preferredDuringSchedulingIgnoredDuringExecution: -# items: -# properties: -# podAffinityTerm: -# properties: -# labelSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaceSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaces: -# items: -# type: string -# type: array -# topologyKey: -# type: string -# required: -# - topologyKey -# type: object -# weight: -# format: int32 -# type: integer -# required: -# - podAffinityTerm -# - weight -# type: object -# type: array -# requiredDuringSchedulingIgnoredDuringExecution: -# items: -# properties: -# labelSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaceSelector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# namespaces: -# items: -# type: string -# type: array -# topologyKey: -# type: string -# required: -# - topologyKey -# type: object -# type: array -# type: object -# type: object -# annotations: -# additionalProperties: -# type: string -# type: object -# builtInAdapter: -# properties: -# env: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# valueFrom: -# properties: -# configMapKeyRef: -# properties: -# key: -# type: string -# name: -# type: string -# optional: -# type: boolean -# required: -# - key -# type: object -# x-kubernetes-map-type: atomic -# fieldRef: -# properties: -# apiVersion: -# type: string -# fieldPath: -# type: string -# required: -# - fieldPath -# type: object -# x-kubernetes-map-type: atomic -# resourceFieldRef: -# properties: -# containerName: -# type: string -# divisor: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# resource: -# type: string -# required: -# - resource -# type: object -# x-kubernetes-map-type: atomic -# secretKeyRef: -# properties: -# key: -# type: string -# name: -# type: string -# optional: -# type: boolean -# required: -# - key -# type: object -# x-kubernetes-map-type: atomic -# type: object -# required: -# - name -# type: object -# type: array -# memBufferBytes: -# type: integer -# modelLoadingTimeoutMillis: -# type: integer -# runtimeManagementPort: -# type: integer -# serverType: -# type: string -# type: object -# containers: -# items: -# properties: -# args: -# items: -# type: string -# type: array -# command: -# items: -# type: string -# type: array -# env: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# valueFrom: -# properties: -# configMapKeyRef: -# properties: -# key: -# type: string -# name: -# type: string -# optional: -# type: boolean -# required: -# - key -# type: object -# x-kubernetes-map-type: atomic -# fieldRef: -# properties: -# apiVersion: -# type: string -# fieldPath: -# type: string -# required: -# - fieldPath -# type: object -# x-kubernetes-map-type: atomic -# resourceFieldRef: -# properties: -# containerName: -# type: string -# divisor: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# resource: -# type: string -# required: -# - resource -# type: object -# x-kubernetes-map-type: atomic -# secretKeyRef: -# properties: -# key: -# type: string -# name: -# type: string -# optional: -# type: boolean -# required: -# - key -# type: object -# x-kubernetes-map-type: atomic -# type: object -# required: -# - name -# type: object -# type: array -# envFrom: -# items: -# properties: -# configMapRef: -# properties: -# name: -# type: string -# optional: -# type: boolean -# type: object -# x-kubernetes-map-type: atomic -# prefix: -# type: string -# secretRef: -# properties: -# name: -# type: string -# optional: -# type: boolean -# type: object -# x-kubernetes-map-type: atomic -# type: object -# type: array -# image: -# type: string -# imagePullPolicy: -# type: string -# lifecycle: -# properties: -# postStart: -# properties: -# exec: -# properties: -# command: -# items: -# type: string -# type: array -# type: object -# httpGet: -# properties: -# host: -# type: string -# httpHeaders: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# required: -# - name -# - value -# type: object -# type: array -# path: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# scheme: -# type: string -# required: -# - port -# type: object -# tcpSocket: -# properties: -# host: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# required: -# - port -# type: object -# type: object -# preStop: -# properties: -# exec: -# properties: -# command: -# items: -# type: string -# type: array -# type: object -# httpGet: -# properties: -# host: -# type: string -# httpHeaders: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# required: -# - name -# - value -# type: object -# type: array -# path: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# scheme: -# type: string -# required: -# - port -# type: object -# tcpSocket: -# properties: -# host: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# required: -# - port -# type: object -# type: object -# type: object -# livenessProbe: -# properties: -# exec: -# properties: -# command: -# items: -# type: string -# type: array -# type: object -# failureThreshold: -# format: int32 -# type: integer -# grpc: -# properties: -# port: -# format: int32 -# type: integer -# service: -# type: string -# required: -# - port -# type: object -# httpGet: -# properties: -# host: -# type: string -# httpHeaders: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# required: -# - name -# - value -# type: object -# type: array -# path: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# scheme: -# type: string -# required: -# - port -# type: object -# initialDelaySeconds: -# format: int32 -# type: integer -# periodSeconds: -# format: int32 -# type: integer -# successThreshold: -# format: int32 -# type: integer -# tcpSocket: -# properties: -# host: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# required: -# - port -# type: object -# terminationGracePeriodSeconds: -# format: int64 -# type: integer -# timeoutSeconds: -# format: int32 -# type: integer -# type: object -# name: -# type: string -# ports: -# items: -# properties: -# containerPort: -# format: int32 -# type: integer -# hostIP: -# type: string -# hostPort: -# format: int32 -# type: integer -# name: -# type: string -# protocol: -# default: TCP -# type: string -# required: -# - containerPort -# type: object -# type: array -# x-kubernetes-list-map-keys: -# - containerPort -# - protocol -# x-kubernetes-list-type: map -# readinessProbe: -# properties: -# exec: -# properties: -# command: -# items: -# type: string -# type: array -# type: object -# failureThreshold: -# format: int32 -# type: integer -# grpc: -# properties: -# port: -# format: int32 -# type: integer -# service: -# type: string -# required: -# - port -# type: object -# httpGet: -# properties: -# host: -# type: string -# httpHeaders: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# required: -# - name -# - value -# type: object -# type: array -# path: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# scheme: -# type: string -# required: -# - port -# type: object -# initialDelaySeconds: -# format: int32 -# type: integer -# periodSeconds: -# format: int32 -# type: integer -# successThreshold: -# format: int32 -# type: integer -# tcpSocket: -# properties: -# host: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# required: -# - port -# type: object -# terminationGracePeriodSeconds: -# format: int64 -# type: integer -# timeoutSeconds: -# format: int32 -# type: integer -# type: object -# resizePolicy: -# items: -# properties: -# resourceName: -# type: string -# restartPolicy: -# type: string -# required: -# - resourceName -# - restartPolicy -# type: object -# type: array -# x-kubernetes-list-type: atomic -# resources: -# properties: -# claims: -# items: -# properties: -# name: -# type: string -# required: -# - name -# type: object -# type: array -# x-kubernetes-list-map-keys: -# - name -# x-kubernetes-list-type: map -# limits: -# additionalProperties: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# type: object -# requests: -# additionalProperties: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# type: object -# type: object -# restartPolicy: -# type: string -# securityContext: -# properties: -# allowPrivilegeEscalation: -# type: boolean -# capabilities: -# properties: -# add: -# items: -# type: string -# type: array -# drop: -# items: -# type: string -# type: array -# type: object -# privileged: -# type: boolean -# procMount: -# type: string -# readOnlyRootFilesystem: -# type: boolean -# runAsGroup: -# format: int64 -# type: integer -# runAsNonRoot: -# type: boolean -# runAsUser: -# format: int64 -# type: integer -# seLinuxOptions: -# properties: -# level: -# type: string -# role: -# type: string -# type: -# type: string -# user: -# type: string -# type: object -# seccompProfile: -# properties: -# localhostProfile: -# type: string -# type: -# type: string -# required: -# - type -# type: object -# windowsOptions: -# properties: -# gmsaCredentialSpec: -# type: string -# gmsaCredentialSpecName: -# type: string -# hostProcess: -# type: boolean -# runAsUserName: -# type: string -# type: object -# type: object -# startupProbe: -# properties: -# exec: -# properties: -# command: -# items: -# type: string -# type: array -# type: object -# failureThreshold: -# format: int32 -# type: integer -# grpc: -# properties: -# port: -# format: int32 -# type: integer -# service: -# type: string -# required: -# - port -# type: object -# httpGet: -# properties: -# host: -# type: string -# httpHeaders: -# items: -# properties: -# name: -# type: string -# value: -# type: string -# required: -# - name -# - value -# type: object -# type: array -# path: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# scheme: -# type: string -# required: -# - port -# type: object -# initialDelaySeconds: -# format: int32 -# type: integer -# periodSeconds: -# format: int32 -# type: integer -# successThreshold: -# format: int32 -# type: integer -# tcpSocket: -# properties: -# host: -# type: string -# port: -# anyOf: -# - type: integer -# - type: string -# x-kubernetes-int-or-string: true -# required: -# - port -# type: object -# terminationGracePeriodSeconds: -# format: int64 -# type: integer -# timeoutSeconds: -# format: int32 -# type: integer -# type: object -# stdin: -# type: boolean -# stdinOnce: -# type: boolean -# terminationMessagePath: -# type: string -# terminationMessagePolicy: -# type: string -# tty: -# type: boolean -# volumeDevices: -# items: -# properties: -# devicePath: -# type: string -# name: -# type: string -# required: -# - devicePath -# - name -# type: object -# type: array -# volumeMounts: -# items: -# properties: -# mountPath: -# type: string -# mountPropagation: -# type: string -# name: -# type: string -# readOnly: -# type: boolean -# subPath: -# type: string -# subPathExpr: -# type: string -# required: -# - mountPath -# - name -# type: object -# type: array -# workingDir: -# type: string -# required: -# - name -# type: object -# type: array -# disabled: -# type: boolean -# grpcDataEndpoint: -# type: string -# grpcEndpoint: -# type: string -# httpDataEndpoint: -# type: string -# imagePullSecrets: -# items: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# type: array -# labels: -# additionalProperties: -# type: string -# type: object -# multiModel: -# type: boolean -# nodeSelector: -# additionalProperties: -# type: string -# type: object -# protocolVersions: -# items: -# type: string -# type: array -# replicas: -# type: integer -# storageHelper: -# properties: -# disabled: -# type: boolean -# type: object -# supportedModelFormats: -# items: -# properties: -# autoSelect: -# type: boolean -# name: -# type: string -# priority: -# format: int32 -# minimum: 1 -# type: integer -# version: -# type: string -# required: -# - name -# type: object -# type: array -# tolerations: -# items: -# properties: -# effect: -# type: string -# key: -# type: string -# operator: -# type: string -# tolerationSeconds: -# format: int64 -# type: integer -# value: -# type: string -# type: object -# type: array -# volumes: -# items: -# properties: -# awsElasticBlockStore: -# properties: -# fsType: -# type: string -# partition: -# format: int32 -# type: integer -# readOnly: -# type: boolean -# volumeID: -# type: string -# required: -# - volumeID -# type: object -# azureDisk: -# properties: -# cachingMode: -# type: string -# diskName: -# type: string -# diskURI: -# type: string -# fsType: -# type: string -# kind: -# type: string -# readOnly: -# type: boolean -# required: -# - diskName -# - diskURI -# type: object -# azureFile: -# properties: -# readOnly: -# type: boolean -# secretName: -# type: string -# shareName: -# type: string -# required: -# - secretName -# - shareName -# type: object -# cephfs: -# properties: -# monitors: -# items: -# type: string -# type: array -# path: -# type: string -# readOnly: -# type: boolean -# secretFile: -# type: string -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# user: -# type: string -# required: -# - monitors -# type: object -# cinder: -# properties: -# fsType: -# type: string -# readOnly: -# type: boolean -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# volumeID: -# type: string -# required: -# - volumeID -# type: object -# configMap: -# properties: -# defaultMode: -# format: int32 -# type: integer -# items: -# items: -# properties: -# key: -# type: string -# mode: -# format: int32 -# type: integer -# path: -# type: string -# required: -# - key -# - path -# type: object -# type: array -# name: -# type: string -# optional: -# type: boolean -# type: object -# x-kubernetes-map-type: atomic -# csi: -# properties: -# driver: -# type: string -# fsType: -# type: string -# nodePublishSecretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# readOnly: -# type: boolean -# volumeAttributes: -# additionalProperties: -# type: string -# type: object -# required: -# - driver -# type: object -# downwardAPI: -# properties: -# defaultMode: -# format: int32 -# type: integer -# items: -# items: -# properties: -# fieldRef: -# properties: -# apiVersion: -# type: string -# fieldPath: -# type: string -# required: -# - fieldPath -# type: object -# x-kubernetes-map-type: atomic -# mode: -# format: int32 -# type: integer -# path: -# type: string -# resourceFieldRef: -# properties: -# containerName: -# type: string -# divisor: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# resource: -# type: string -# required: -# - resource -# type: object -# x-kubernetes-map-type: atomic -# required: -# - path -# type: object -# type: array -# type: object -# emptyDir: -# properties: -# medium: -# type: string -# sizeLimit: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# type: object -# ephemeral: -# properties: -# volumeClaimTemplate: -# properties: -# metadata: -# type: object -# spec: -# properties: -# accessModes: -# items: -# type: string -# type: array -# dataSource: -# properties: -# apiGroup: -# type: string -# kind: -# type: string -# name: -# type: string -# required: -# - kind -# - name -# type: object -# x-kubernetes-map-type: atomic -# dataSourceRef: -# properties: -# apiGroup: -# type: string -# kind: -# type: string -# name: -# type: string -# namespace: -# type: string -# required: -# - kind -# - name -# type: object -# resources: -# properties: -# claims: -# items: -# properties: -# name: -# type: string -# required: -# - name -# type: object -# type: array -# x-kubernetes-list-map-keys: -# - name -# x-kubernetes-list-type: map -# limits: -# additionalProperties: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# type: object -# requests: -# additionalProperties: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# type: object -# type: object -# selector: -# properties: -# matchExpressions: -# items: -# properties: -# key: -# type: string -# operator: -# type: string -# values: -# items: -# type: string -# type: array -# required: -# - key -# - operator -# type: object -# type: array -# matchLabels: -# additionalProperties: -# type: string -# type: object -# type: object -# x-kubernetes-map-type: atomic -# storageClassName: -# type: string -# volumeMode: -# type: string -# volumeName: -# type: string -# type: object -# required: -# - spec -# type: object -# type: object -# fc: -# properties: -# fsType: -# type: string -# lun: -# format: int32 -# type: integer -# readOnly: -# type: boolean -# targetWWNs: -# items: -# type: string -# type: array -# wwids: -# items: -# type: string -# type: array -# type: object -# flexVolume: -# properties: -# driver: -# type: string -# fsType: -# type: string -# options: -# additionalProperties: -# type: string -# type: object -# readOnly: -# type: boolean -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# required: -# - driver -# type: object -# flocker: -# properties: -# datasetName: -# type: string -# datasetUUID: -# type: string -# type: object -# gcePersistentDisk: -# properties: -# fsType: -# type: string -# partition: -# format: int32 -# type: integer -# pdName: -# type: string -# readOnly: -# type: boolean -# required: -# - pdName -# type: object -# gitRepo: -# properties: -# directory: -# type: string -# repository: -# type: string -# revision: -# type: string -# required: -# - repository -# type: object -# glusterfs: -# properties: -# endpoints: -# type: string -# path: -# type: string -# readOnly: -# type: boolean -# required: -# - endpoints -# - path -# type: object -# hostPath: -# properties: -# path: -# type: string -# type: -# type: string -# required: -# - path -# type: object -# iscsi: -# properties: -# chapAuthDiscovery: -# type: boolean -# chapAuthSession: -# type: boolean -# fsType: -# type: string -# initiatorName: -# type: string -# iqn: -# type: string -# iscsiInterface: -# type: string -# lun: -# format: int32 -# type: integer -# portals: -# items: -# type: string -# type: array -# readOnly: -# type: boolean -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# targetPortal: -# type: string -# required: -# - iqn -# - lun -# - targetPortal -# type: object -# name: -# type: string -# nfs: -# properties: -# path: -# type: string -# readOnly: -# type: boolean -# server: -# type: string -# required: -# - path -# - server -# type: object -# persistentVolumeClaim: -# properties: -# claimName: -# type: string -# readOnly: -# type: boolean -# required: -# - claimName -# type: object -# photonPersistentDisk: -# properties: -# fsType: -# type: string -# pdID: -# type: string -# required: -# - pdID -# type: object -# portworxVolume: -# properties: -# fsType: -# type: string -# readOnly: -# type: boolean -# volumeID: -# type: string -# required: -# - volumeID -# type: object -# projected: -# properties: -# defaultMode: -# format: int32 -# type: integer -# sources: -# items: -# properties: -# configMap: -# properties: -# items: -# items: -# properties: -# key: -# type: string -# mode: -# format: int32 -# type: integer -# path: -# type: string -# required: -# - key -# - path -# type: object -# type: array -# name: -# type: string -# optional: -# type: boolean -# type: object -# x-kubernetes-map-type: atomic -# downwardAPI: -# properties: -# items: -# items: -# properties: -# fieldRef: -# properties: -# apiVersion: -# type: string -# fieldPath: -# type: string -# required: -# - fieldPath -# type: object -# x-kubernetes-map-type: atomic -# mode: -# format: int32 -# type: integer -# path: -# type: string -# resourceFieldRef: -# properties: -# containerName: -# type: string -# divisor: -# anyOf: -# - type: integer -# - type: string -# pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ -# x-kubernetes-int-or-string: true -# resource: -# type: string -# required: -# - resource -# type: object -# x-kubernetes-map-type: atomic -# required: -# - path -# type: object -# type: array -# type: object -# secret: -# properties: -# items: -# items: -# properties: -# key: -# type: string -# mode: -# format: int32 -# type: integer -# path: -# type: string -# required: -# - key -# - path -# type: object -# type: array -# name: -# type: string -# optional: -# type: boolean -# type: object -# x-kubernetes-map-type: atomic -# serviceAccountToken: -# properties: -# audience: -# type: string -# expirationSeconds: -# format: int64 -# type: integer -# path: -# type: string -# required: -# - path -# type: object -# type: object -# type: array -# type: object -# quobyte: -# properties: -# group: -# type: string -# readOnly: -# type: boolean -# registry: -# type: string -# tenant: -# type: string -# user: -# type: string -# volume: -# type: string -# required: -# - registry -# - volume -# type: object -# rbd: -# properties: -# fsType: -# type: string -# image: -# type: string -# keyring: -# type: string -# monitors: -# items: -# type: string -# type: array -# pool: -# type: string -# readOnly: -# type: boolean -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# user: -# type: string -# required: -# - image -# - monitors -# type: object -# scaleIO: -# properties: -# fsType: -# type: string -# gateway: -# type: string -# protectionDomain: -# type: string -# readOnly: -# type: boolean -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# sslEnabled: -# type: boolean -# storageMode: -# type: string -# storagePool: -# type: string -# system: -# type: string -# volumeName: -# type: string -# required: -# - gateway -# - secretRef -# - system -# type: object -# secret: -# properties: -# defaultMode: -# format: int32 -# type: integer -# items: -# items: -# properties: -# key: -# type: string -# mode: -# format: int32 -# type: integer -# path: -# type: string -# required: -# - key -# - path -# type: object -# type: array -# optional: -# type: boolean -# secretName: -# type: string -# type: object -# storageos: -# properties: -# fsType: -# type: string -# readOnly: -# type: boolean -# secretRef: -# properties: -# name: -# type: string -# type: object -# x-kubernetes-map-type: atomic -# volumeName: -# type: string -# volumeNamespace: -# type: string -# type: object -# vsphereVolume: -# properties: -# fsType: -# type: string -# storagePolicyID: -# type: string -# storagePolicyName: -# type: string -# volumePath: -# type: string -# required: -# - volumePath -# type: object -# required: -# - name -# type: object -# type: array -# required: -# - containers -# type: object -# status: -# type: object -# type: object -# served: true -# storage: true -# subresources: {} -#--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -5408,6 +3513,24 @@ spec: - name type: object type: array + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object dnsConfig: properties: nameservers: @@ -8053,6 +6176,24 @@ spec: - name type: object type: array + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object dnsConfig: properties: nameservers: @@ -17606,6 +15747,24 @@ spec: - name type: object type: array + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object dnsConfig: properties: nameservers: