From b5f5fa2ed7c7bff19e95f9c3d0d87d1bf615fbcc Mon Sep 17 00:00:00 2001 From: abchoo <77467773+abchoo@users.noreply.github.com> Date: Fri, 15 Jan 2021 18:57:43 -0500 Subject: [PATCH] Set flags for TrainedModelSpec to be included in openapi-gen (#1302) * Included openapi-gen for Trained Model Spec * Generated python file for trained model spec * Result of openapi-gen * Revert "Result of openapi-gen" This reverts commit 4ddf01777e3e408e43ae268a20e9411ad242bc04. * Result of openapi-gen * Included modelspec with openapi-gen * Client gen for model spec * Added correct parameters * Added dummy model to parameter * Imported V1alpha1TrainedModel * Removed invalid character * Add correct parameters * Fixing invalid syntax --- hack/violation_exceptions.list | 1 + pkg/apis/serving/v1alpha1/trained_model.go | 2 + pkg/apis/serving/v1beta1/openapi_generated.go | 67 ++++++ pkg/apis/serving/v1beta1/swagger.json | 40 ++++ python/kfserving/docs/V1alpha1ModelSpec.md | 13 ++ .../docs/V1alpha1TrainedModelSpec.md | 12 ++ .../docs/V1beta1ComponentStatusSpec.md | 7 +- .../kfserving/docs/V1beta1TorchServeSpec.md | 2 +- python/kfserving/kfserving/models/__init__.py | 2 + .../kfserving/models/v1alpha1_model_spec.py | 192 ++++++++++++++++++ .../models/v1alpha1_trained_model_spec.py | 164 +++++++++++++++ .../models/v1beta1_component_status_spec.py | 102 ++++++---- .../models/v1beta1_torch_serve_spec.py | 4 +- .../test/test_v1alpha1_model_spec.py | 70 +++++++ .../test/test_v1alpha1_trained_model_spec.py | 81 ++++++++ .../test_v1beta1_component_status_spec.py | 7 +- .../test/test_v1beta1_inference_service.py | 7 +- .../test_v1beta1_inference_service_list.py | 12 +- .../test_v1beta1_inference_service_status.py | 5 +- 19 files changed, 734 insertions(+), 56 deletions(-) create mode 100644 python/kfserving/docs/V1alpha1ModelSpec.md create mode 100644 python/kfserving/docs/V1alpha1TrainedModelSpec.md create mode 100644 python/kfserving/kfserving/models/v1alpha1_model_spec.py create mode 100644 python/kfserving/kfserving/models/v1alpha1_trained_model_spec.py create mode 100644 python/kfserving/test/test_v1alpha1_model_spec.py create mode 100644 python/kfserving/test/test_v1alpha1_trained_model_spec.py diff --git a/hack/violation_exceptions.list b/hack/violation_exceptions.list index dfbc7c14e68..25a5e1a9d9e 100644 --- a/hack/violation_exceptions.list +++ b/hack/violation_exceptions.list @@ -7,6 +7,7 @@ API rule violation: list_type_missing,./pkg/apis/serving/v1beta1,PodSpec,InitCon API rule violation: list_type_missing,./pkg/apis/serving/v1beta1,PodSpec,ReadinessGates API rule violation: list_type_missing,./pkg/apis/serving/v1beta1,PodSpec,Tolerations API rule violation: list_type_missing,./pkg/apis/serving/v1beta1,PodSpec,Volumes +API rule violation: names_match,./pkg/apis/serving/v1alpha1,ModelSpec,StorageURI API rule violation: names_match,./pkg/apis/serving/v1beta1,AlibiExplainerSpec,StorageURI API rule violation: names_match,./pkg/apis/serving/v1beta1,ComponentExtensionSpec,TimeoutSeconds API rule violation: names_match,./pkg/apis/serving/v1beta1,ExplainerConfig,ContainerImage diff --git a/pkg/apis/serving/v1alpha1/trained_model.go b/pkg/apis/serving/v1alpha1/trained_model.go index e2a55fcf025..1feaa44389d 100644 --- a/pkg/apis/serving/v1alpha1/trained_model.go +++ b/pkg/apis/serving/v1alpha1/trained_model.go @@ -47,6 +47,7 @@ type TrainedModelList struct { } // TrainedModelSpec defines the trained model spec +// +k8s:openapi-gen=true type TrainedModelSpec struct { // parent inference service to deploy to // +required @@ -57,6 +58,7 @@ type TrainedModelSpec struct { } // ModelSpec describes a trained model +// +k8s:openapi-gen=true type ModelSpec struct { // Storage URI for the model repository StorageURI string `json:"storageUri"` diff --git a/pkg/apis/serving/v1beta1/openapi_generated.go b/pkg/apis/serving/v1beta1/openapi_generated.go index 7126aea5de4..072c4b057c6 100644 --- a/pkg/apis/serving/v1beta1/openapi_generated.go +++ b/pkg/apis/serving/v1beta1/openapi_generated.go @@ -29,8 +29,10 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ + "./pkg/apis/serving/v1alpha1.ModelSpec": schema_pkg_apis_serving_v1alpha1_ModelSpec(ref), "./pkg/apis/serving/v1alpha1.TrainedModel": schema_pkg_apis_serving_v1alpha1_TrainedModel(ref), "./pkg/apis/serving/v1alpha1.TrainedModelList": schema_pkg_apis_serving_v1alpha1_TrainedModelList(ref), + "./pkg/apis/serving/v1alpha1.TrainedModelSpec": schema_pkg_apis_serving_v1alpha1_TrainedModelSpec(ref), "./pkg/apis/serving/v1beta1.AIXExplainerSpec": schema_pkg_apis_serving_v1beta1_AIXExplainerSpec(ref), "./pkg/apis/serving/v1beta1.ARTExplainerSpec": schema_pkg_apis_serving_v1beta1_ARTExplainerSpec(ref), "./pkg/apis/serving/v1beta1.AlibiExplainerSpec": schema_pkg_apis_serving_v1beta1_AlibiExplainerSpec(ref), @@ -71,6 +73,42 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA } } +func schema_pkg_apis_serving_v1alpha1_ModelSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ModelSpec describes a trained model", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "storageUri": { + SchemaProps: spec.SchemaProps{ + Description: "Storage URI for the model repository", + Type: []string{"string"}, + Format: "", + }, + }, + "framework": { + SchemaProps: spec.SchemaProps{ + Description: "Machine Learning The values could be: \"tensorflow\",\"pytorch\",\"sklearn\",\"onnx\",\"xgboost\", \"myawesomeinternalframework\" etc.", + Type: []string{"string"}, + Format: "", + }, + }, + "memory": { + SchemaProps: spec.SchemaProps{ + Description: "Maximum memory this model will consume, this field is used to decide if a model server has enough memory to load this model.", + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + Required: []string{"storageUri", "framework"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + } +} + func schema_pkg_apis_serving_v1alpha1_TrainedModel(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -167,6 +205,35 @@ func schema_pkg_apis_serving_v1alpha1_TrainedModelList(ref common.ReferenceCallb } } +func schema_pkg_apis_serving_v1alpha1_TrainedModelSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TrainedModelSpec defines the trained model spec", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "inferenceService": { + SchemaProps: spec.SchemaProps{ + Description: "parent inference service to deploy to", + Type: []string{"string"}, + Format: "", + }, + }, + "model": { + SchemaProps: spec.SchemaProps{ + Description: "Predictor model spec", + Ref: ref("./pkg/apis/serving/v1alpha1.ModelSpec"), + }, + }, + }, + Required: []string{"inferenceService", "model"}, + }, + }, + Dependencies: []string{ + "./pkg/apis/serving/v1alpha1.ModelSpec"}, + } +} + func schema_pkg_apis_serving_v1beta1_AIXExplainerSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/serving/v1beta1/swagger.json b/pkg/apis/serving/v1beta1/swagger.json index 142522b07d4..66d1d5a4a81 100644 --- a/pkg/apis/serving/v1beta1/swagger.json +++ b/pkg/apis/serving/v1beta1/swagger.json @@ -7,6 +7,28 @@ }, "paths": {}, "definitions": { + "v1alpha1.ModelSpec": { + "description": "ModelSpec describes a trained model", + "type": "object", + "required": [ + "storageUri", + "framework" + ], + "properties": { + "framework": { + "description": "Machine Learning \u003cframework name\u003e The values could be: \"tensorflow\",\"pytorch\",\"sklearn\",\"onnx\",\"xgboost\", \"myawesomeinternalframework\" etc.", + "type": "string" + }, + "memory": { + "description": "Maximum memory this model will consume, this field is used to decide if a model server has enough memory to load this model.", + "$ref": "#/definitions/resource.Quantity" + }, + "storageUri": { + "description": "Storage URI for the model repository", + "type": "string" + } + } + }, "v1alpha1.TrainedModel": { "description": "TrainedModel is the Schema for the TrainedModel API", "type": "object", @@ -57,6 +79,24 @@ } } }, + "v1alpha1.TrainedModelSpec": { + "description": "TrainedModelSpec defines the trained model spec", + "type": "object", + "required": [ + "inferenceService", + "model" + ], + "properties": { + "inferenceService": { + "description": "parent inference service to deploy to", + "type": "string" + }, + "model": { + "description": "Predictor model spec", + "$ref": "#/definitions/v1alpha1.ModelSpec" + } + } + }, "v1beta1.AIXExplainerSpec": { "description": "AIXExplainerSpec defines the arguments for configuring an AIX Explanation Server", "type": "object", diff --git a/python/kfserving/docs/V1alpha1ModelSpec.md b/python/kfserving/docs/V1alpha1ModelSpec.md new file mode 100644 index 00000000000..1e89d45b4cc --- /dev/null +++ b/python/kfserving/docs/V1alpha1ModelSpec.md @@ -0,0 +1,13 @@ +# V1alpha1ModelSpec + +ModelSpec describes a trained model +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**framework** | **str** | Machine Learning <framework name> The values could be: \"tensorflow\",\"pytorch\",\"sklearn\",\"onnx\",\"xgboost\", \"myawesomeinternalframework\" etc. | +**memory** | [**ResourceQuantity**](ResourceQuantity.md) | | [optional] +**storage_uri** | **str** | Storage URI for the model repository | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python/kfserving/docs/V1alpha1TrainedModelSpec.md b/python/kfserving/docs/V1alpha1TrainedModelSpec.md new file mode 100644 index 00000000000..52abe76454e --- /dev/null +++ b/python/kfserving/docs/V1alpha1TrainedModelSpec.md @@ -0,0 +1,12 @@ +# V1alpha1TrainedModelSpec + +TrainedModelSpec defines the trained model spec +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**inference_service** | **str** | parent inference service to deploy to | +**model** | [**V1alpha1ModelSpec**](V1alpha1ModelSpec.md) | | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python/kfserving/docs/V1beta1ComponentStatusSpec.md b/python/kfserving/docs/V1beta1ComponentStatusSpec.md index cc3d36927b6..2f4ec119a84 100644 --- a/python/kfserving/docs/V1beta1ComponentStatusSpec.md +++ b/python/kfserving/docs/V1beta1ComponentStatusSpec.md @@ -5,10 +5,11 @@ ComponentStatusSpec describes the state of the component Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **address** | [**KnativeAddressable**](KnativeAddressable.md) | | [optional] -**latest_created_revision** | **str** | Latest revision name that is in created | [optional] +**latest_created_revision** | **str** | Latest revision name that is created | [optional] **latest_ready_revision** | **str** | Latest revision name that is in ready state | [optional] -**previous_ready_revision** | **str** | Previous revision name that is in ready state | [optional] -**traffic_percent** | **int** | Traffic percent on the latest ready revision | [optional] +**latest_rolledout_revision** | **str** | Latest revision name that is rolled out with 100 percent traffic | [optional] +**previous_rolledout_revision** | **str** | Previous revision name that is rolled out with 100 percent traffic | [optional] +**traffic** | [**list[KnativeDevServingPkgApisServingV1TrafficTarget]**](KnativeDevServingPkgApisServingV1TrafficTarget.md) | Traffic holds the configured traffic distribution for latest ready revision and previous rolled out revision. | [optional] **url** | [**KnativeURL**](KnativeURL.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/python/kfserving/docs/V1beta1TorchServeSpec.md b/python/kfserving/docs/V1beta1TorchServeSpec.md index 2346c2b1115..2b6bb952c5f 100644 --- a/python/kfserving/docs/V1beta1TorchServeSpec.md +++ b/python/kfserving/docs/V1beta1TorchServeSpec.md @@ -12,7 +12,7 @@ Name | Type | Description | Notes **image_pull_policy** | **str** | Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images | [optional] **lifecycle** | [**V1Lifecycle**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Lifecycle.md) | | [optional] **liveness_probe** | [**V1Probe**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Probe.md) | | [optional] -**model_class_name** | **str** | Defaults PyTorch model class name to 'PyTorchModel' | [optional] +**model_class_name** | **str** | When this field is specified KFS chooses the KFServer implementation, otherwise KFS uses the TorchServe implementation | [optional] **name** | **str** | Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. | [optional] **ports** | [**list[V1ContainerPort]**](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1ContainerPort.md) | List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated. | [optional] **protocol_version** | **str** | Protocol version to use by the predictor (i.e. v1 or v2) | [optional] diff --git a/python/kfserving/kfserving/models/__init__.py b/python/kfserving/kfserving/models/__init__.py index 14c18796a50..e32458f0163 100644 --- a/python/kfserving/kfserving/models/__init__.py +++ b/python/kfserving/kfserving/models/__init__.py @@ -28,8 +28,10 @@ from __future__ import absolute_import # import models into model package +from kfserving.models.v1alpha1_model_spec import V1alpha1ModelSpec from kfserving.models.v1alpha1_trained_model import V1alpha1TrainedModel from kfserving.models.v1alpha1_trained_model_list import V1alpha1TrainedModelList +from kfserving.models.v1alpha1_trained_model_spec import V1alpha1TrainedModelSpec from kfserving.models.v1beta1_aix_explainer_spec import V1beta1AIXExplainerSpec from kfserving.models.v1beta1_art_explainer_spec import V1beta1ARTExplainerSpec from kfserving.models.v1beta1_alibi_explainer_spec import V1beta1AlibiExplainerSpec diff --git a/python/kfserving/kfserving/models/v1alpha1_model_spec.py b/python/kfserving/kfserving/models/v1alpha1_model_spec.py new file mode 100644 index 00000000000..df11ab890a6 --- /dev/null +++ b/python/kfserving/kfserving/models/v1alpha1_model_spec.py @@ -0,0 +1,192 @@ +# Copyright 2020 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# coding: utf-8 + +""" + KFServing + + Python SDK for KFServing # noqa: E501 + + The version of the OpenAPI document: v0.1 + Generated by: https://openapi-generator.tech +""" + + +import pprint +import re # noqa: F401 + +import six + +from kfserving.configuration import Configuration + + +class V1alpha1ModelSpec(object): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + Attributes: + openapi_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + openapi_types = { + 'framework': 'str', + 'memory': 'ResourceQuantity', + 'storage_uri': 'str' + } + + attribute_map = { + 'framework': 'framework', + 'memory': 'memory', + 'storage_uri': 'storageUri' + } + + def __init__(self, framework=None, memory=None, storage_uri=None, local_vars_configuration=None): # noqa: E501 + """V1alpha1ModelSpec - a model defined in OpenAPI""" # noqa: E501 + if local_vars_configuration is None: + local_vars_configuration = Configuration() + self.local_vars_configuration = local_vars_configuration + + self._framework = None + self._memory = None + self._storage_uri = None + self.discriminator = None + + self.framework = framework + if memory is not None: + self.memory = memory + self.storage_uri = storage_uri + + @property + def framework(self): + """Gets the framework of this V1alpha1ModelSpec. # noqa: E501 + + Machine Learning The values could be: \"tensorflow\",\"pytorch\",\"sklearn\",\"onnx\",\"xgboost\", \"myawesomeinternalframework\" etc. # noqa: E501 + + :return: The framework of this V1alpha1ModelSpec. # noqa: E501 + :rtype: str + """ + return self._framework + + @framework.setter + def framework(self, framework): + """Sets the framework of this V1alpha1ModelSpec. + + Machine Learning The values could be: \"tensorflow\",\"pytorch\",\"sklearn\",\"onnx\",\"xgboost\", \"myawesomeinternalframework\" etc. # noqa: E501 + + :param framework: The framework of this V1alpha1ModelSpec. # noqa: E501 + :type: str + """ + if self.local_vars_configuration.client_side_validation and framework is None: # noqa: E501 + raise ValueError("Invalid value for `framework`, must not be `None`") # noqa: E501 + + self._framework = framework + + @property + def memory(self): + """Gets the memory of this V1alpha1ModelSpec. # noqa: E501 + + + :return: The memory of this V1alpha1ModelSpec. # noqa: E501 + :rtype: ResourceQuantity + """ + return self._memory + + @memory.setter + def memory(self, memory): + """Sets the memory of this V1alpha1ModelSpec. + + + :param memory: The memory of this V1alpha1ModelSpec. # noqa: E501 + :type: ResourceQuantity + """ + + self._memory = memory + + @property + def storage_uri(self): + """Gets the storage_uri of this V1alpha1ModelSpec. # noqa: E501 + + Storage URI for the model repository # noqa: E501 + + :return: The storage_uri of this V1alpha1ModelSpec. # noqa: E501 + :rtype: str + """ + return self._storage_uri + + @storage_uri.setter + def storage_uri(self, storage_uri): + """Sets the storage_uri of this V1alpha1ModelSpec. + + Storage URI for the model repository # noqa: E501 + + :param storage_uri: The storage_uri of this V1alpha1ModelSpec. # noqa: E501 + :type: str + """ + if self.local_vars_configuration.client_side_validation and storage_uri is None: # noqa: E501 + raise ValueError("Invalid value for `storage_uri`, must not be `None`") # noqa: E501 + + self._storage_uri = storage_uri + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.openapi_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, V1alpha1ModelSpec): + return False + + return self.to_dict() == other.to_dict() + + def __ne__(self, other): + """Returns true if both objects are not equal""" + if not isinstance(other, V1alpha1ModelSpec): + return True + + return self.to_dict() != other.to_dict() diff --git a/python/kfserving/kfserving/models/v1alpha1_trained_model_spec.py b/python/kfserving/kfserving/models/v1alpha1_trained_model_spec.py new file mode 100644 index 00000000000..3d135267b80 --- /dev/null +++ b/python/kfserving/kfserving/models/v1alpha1_trained_model_spec.py @@ -0,0 +1,164 @@ +# Copyright 2020 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# coding: utf-8 + +""" + KFServing + + Python SDK for KFServing # noqa: E501 + + The version of the OpenAPI document: v0.1 + Generated by: https://openapi-generator.tech +""" + + +import pprint +import re # noqa: F401 + +import six + +from kfserving.configuration import Configuration + + +class V1alpha1TrainedModelSpec(object): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + Attributes: + openapi_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + openapi_types = { + 'inference_service': 'str', + 'model': 'V1alpha1ModelSpec' + } + + attribute_map = { + 'inference_service': 'inferenceService', + 'model': 'model' + } + + def __init__(self, inference_service=None, model=None, local_vars_configuration=None): # noqa: E501 + """V1alpha1TrainedModelSpec - a model defined in OpenAPI""" # noqa: E501 + if local_vars_configuration is None: + local_vars_configuration = Configuration() + self.local_vars_configuration = local_vars_configuration + + self._inference_service = None + self._model = None + self.discriminator = None + + self.inference_service = inference_service + self.model = model + + @property + def inference_service(self): + """Gets the inference_service of this V1alpha1TrainedModelSpec. # noqa: E501 + + parent inference service to deploy to # noqa: E501 + + :return: The inference_service of this V1alpha1TrainedModelSpec. # noqa: E501 + :rtype: str + """ + return self._inference_service + + @inference_service.setter + def inference_service(self, inference_service): + """Sets the inference_service of this V1alpha1TrainedModelSpec. + + parent inference service to deploy to # noqa: E501 + + :param inference_service: The inference_service of this V1alpha1TrainedModelSpec. # noqa: E501 + :type: str + """ + if self.local_vars_configuration.client_side_validation and inference_service is None: # noqa: E501 + raise ValueError("Invalid value for `inference_service`, must not be `None`") # noqa: E501 + + self._inference_service = inference_service + + @property + def model(self): + """Gets the model of this V1alpha1TrainedModelSpec. # noqa: E501 + + + :return: The model of this V1alpha1TrainedModelSpec. # noqa: E501 + :rtype: V1alpha1ModelSpec + """ + return self._model + + @model.setter + def model(self, model): + """Sets the model of this V1alpha1TrainedModelSpec. + + + :param model: The model of this V1alpha1TrainedModelSpec. # noqa: E501 + :type: V1alpha1ModelSpec + """ + if self.local_vars_configuration.client_side_validation and model is None: # noqa: E501 + raise ValueError("Invalid value for `model`, must not be `None`") # noqa: E501 + + self._model = model + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.openapi_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, V1alpha1TrainedModelSpec): + return False + + return self.to_dict() == other.to_dict() + + def __ne__(self, other): + """Returns true if both objects are not equal""" + if not isinstance(other, V1alpha1TrainedModelSpec): + return True + + return self.to_dict() != other.to_dict() diff --git a/python/kfserving/kfserving/models/v1beta1_component_status_spec.py b/python/kfserving/kfserving/models/v1beta1_component_status_spec.py index ebcc4764b86..18eedc8d84c 100644 --- a/python/kfserving/kfserving/models/v1beta1_component_status_spec.py +++ b/python/kfserving/kfserving/models/v1beta1_component_status_spec.py @@ -50,8 +50,9 @@ class V1beta1ComponentStatusSpec(object): 'address': 'KnativeAddressable', 'latest_created_revision': 'str', 'latest_ready_revision': 'str', - 'previous_ready_revision': 'str', - 'traffic_percent': 'int', + 'latest_rolledout_revision': 'str', + 'previous_rolledout_revision': 'str', + 'traffic': 'list[KnativeDevServingPkgApisServingV1TrafficTarget]', 'url': 'KnativeURL' } @@ -59,12 +60,13 @@ class V1beta1ComponentStatusSpec(object): 'address': 'address', 'latest_created_revision': 'latestCreatedRevision', 'latest_ready_revision': 'latestReadyRevision', - 'previous_ready_revision': 'previousReadyRevision', - 'traffic_percent': 'trafficPercent', + 'latest_rolledout_revision': 'latestRolledoutRevision', + 'previous_rolledout_revision': 'previousRolledoutRevision', + 'traffic': 'traffic', 'url': 'url' } - def __init__(self, address=None, latest_created_revision=None, latest_ready_revision=None, previous_ready_revision=None, traffic_percent=None, url=None, local_vars_configuration=None): # noqa: E501 + def __init__(self, address=None, latest_created_revision=None, latest_ready_revision=None, latest_rolledout_revision=None, previous_rolledout_revision=None, traffic=None, url=None, local_vars_configuration=None): # noqa: E501 """V1beta1ComponentStatusSpec - a model defined in OpenAPI""" # noqa: E501 if local_vars_configuration is None: local_vars_configuration = Configuration() @@ -73,8 +75,9 @@ def __init__(self, address=None, latest_created_revision=None, latest_ready_revi self._address = None self._latest_created_revision = None self._latest_ready_revision = None - self._previous_ready_revision = None - self._traffic_percent = None + self._latest_rolledout_revision = None + self._previous_rolledout_revision = None + self._traffic = None self._url = None self.discriminator = None @@ -84,10 +87,12 @@ def __init__(self, address=None, latest_created_revision=None, latest_ready_revi self.latest_created_revision = latest_created_revision if latest_ready_revision is not None: self.latest_ready_revision = latest_ready_revision - if previous_ready_revision is not None: - self.previous_ready_revision = previous_ready_revision - if traffic_percent is not None: - self.traffic_percent = traffic_percent + if latest_rolledout_revision is not None: + self.latest_rolledout_revision = latest_rolledout_revision + if previous_rolledout_revision is not None: + self.previous_rolledout_revision = previous_rolledout_revision + if traffic is not None: + self.traffic = traffic if url is not None: self.url = url @@ -116,7 +121,7 @@ def address(self, address): def latest_created_revision(self): """Gets the latest_created_revision of this V1beta1ComponentStatusSpec. # noqa: E501 - Latest revision name that is in created # noqa: E501 + Latest revision name that is created # noqa: E501 :return: The latest_created_revision of this V1beta1ComponentStatusSpec. # noqa: E501 :rtype: str @@ -127,7 +132,7 @@ def latest_created_revision(self): def latest_created_revision(self, latest_created_revision): """Sets the latest_created_revision of this V1beta1ComponentStatusSpec. - Latest revision name that is in created # noqa: E501 + Latest revision name that is created # noqa: E501 :param latest_created_revision: The latest_created_revision of this V1beta1ComponentStatusSpec. # noqa: E501 :type: str @@ -159,50 +164,73 @@ def latest_ready_revision(self, latest_ready_revision): self._latest_ready_revision = latest_ready_revision @property - def previous_ready_revision(self): - """Gets the previous_ready_revision of this V1beta1ComponentStatusSpec. # noqa: E501 + def latest_rolledout_revision(self): + """Gets the latest_rolledout_revision of this V1beta1ComponentStatusSpec. # noqa: E501 - Previous revision name that is in ready state # noqa: E501 + Latest revision name that is rolled out with 100 percent traffic # noqa: E501 - :return: The previous_ready_revision of this V1beta1ComponentStatusSpec. # noqa: E501 + :return: The latest_rolledout_revision of this V1beta1ComponentStatusSpec. # noqa: E501 :rtype: str """ - return self._previous_ready_revision + return self._latest_rolledout_revision - @previous_ready_revision.setter - def previous_ready_revision(self, previous_ready_revision): - """Sets the previous_ready_revision of this V1beta1ComponentStatusSpec. + @latest_rolledout_revision.setter + def latest_rolledout_revision(self, latest_rolledout_revision): + """Sets the latest_rolledout_revision of this V1beta1ComponentStatusSpec. - Previous revision name that is in ready state # noqa: E501 + Latest revision name that is rolled out with 100 percent traffic # noqa: E501 - :param previous_ready_revision: The previous_ready_revision of this V1beta1ComponentStatusSpec. # noqa: E501 + :param latest_rolledout_revision: The latest_rolledout_revision of this V1beta1ComponentStatusSpec. # noqa: E501 :type: str """ - self._previous_ready_revision = previous_ready_revision + self._latest_rolledout_revision = latest_rolledout_revision @property - def traffic_percent(self): - """Gets the traffic_percent of this V1beta1ComponentStatusSpec. # noqa: E501 + def previous_rolledout_revision(self): + """Gets the previous_rolledout_revision of this V1beta1ComponentStatusSpec. # noqa: E501 - Traffic percent on the latest ready revision # noqa: E501 + Previous revision name that is rolled out with 100 percent traffic # noqa: E501 - :return: The traffic_percent of this V1beta1ComponentStatusSpec. # noqa: E501 - :rtype: int + :return: The previous_rolledout_revision of this V1beta1ComponentStatusSpec. # noqa: E501 + :rtype: str + """ + return self._previous_rolledout_revision + + @previous_rolledout_revision.setter + def previous_rolledout_revision(self, previous_rolledout_revision): + """Sets the previous_rolledout_revision of this V1beta1ComponentStatusSpec. + + Previous revision name that is rolled out with 100 percent traffic # noqa: E501 + + :param previous_rolledout_revision: The previous_rolledout_revision of this V1beta1ComponentStatusSpec. # noqa: E501 + :type: str + """ + + self._previous_rolledout_revision = previous_rolledout_revision + + @property + def traffic(self): + """Gets the traffic of this V1beta1ComponentStatusSpec. # noqa: E501 + + Traffic holds the configured traffic distribution for latest ready revision and previous rolled out revision. # noqa: E501 + + :return: The traffic of this V1beta1ComponentStatusSpec. # noqa: E501 + :rtype: list[KnativeDevServingPkgApisServingV1TrafficTarget] """ - return self._traffic_percent + return self._traffic - @traffic_percent.setter - def traffic_percent(self, traffic_percent): - """Sets the traffic_percent of this V1beta1ComponentStatusSpec. + @traffic.setter + def traffic(self, traffic): + """Sets the traffic of this V1beta1ComponentStatusSpec. - Traffic percent on the latest ready revision # noqa: E501 + Traffic holds the configured traffic distribution for latest ready revision and previous rolled out revision. # noqa: E501 - :param traffic_percent: The traffic_percent of this V1beta1ComponentStatusSpec. # noqa: E501 - :type: int + :param traffic: The traffic of this V1beta1ComponentStatusSpec. # noqa: E501 + :type: list[KnativeDevServingPkgApisServingV1TrafficTarget] """ - self._traffic_percent = traffic_percent + self._traffic = traffic @property def url(self): diff --git a/python/kfserving/kfserving/models/v1beta1_torch_serve_spec.py b/python/kfserving/kfserving/models/v1beta1_torch_serve_spec.py index f1a7efff05b..430d6e53cb4 100644 --- a/python/kfserving/kfserving/models/v1beta1_torch_serve_spec.py +++ b/python/kfserving/kfserving/models/v1beta1_torch_serve_spec.py @@ -375,7 +375,7 @@ def liveness_probe(self, liveness_probe): def model_class_name(self): """Gets the model_class_name of this V1beta1TorchServeSpec. # noqa: E501 - Defaults PyTorch model class name to 'PyTorchModel' # noqa: E501 + When this field is specified KFS chooses the KFServer implementation, otherwise KFS uses the TorchServe implementation # noqa: E501 :return: The model_class_name of this V1beta1TorchServeSpec. # noqa: E501 :rtype: str @@ -386,7 +386,7 @@ def model_class_name(self): def model_class_name(self, model_class_name): """Sets the model_class_name of this V1beta1TorchServeSpec. - Defaults PyTorch model class name to 'PyTorchModel' # noqa: E501 + When this field is specified KFS chooses the KFServer implementation, otherwise KFS uses the TorchServe implementation # noqa: E501 :param model_class_name: The model_class_name of this V1beta1TorchServeSpec. # noqa: E501 :type: str diff --git a/python/kfserving/test/test_v1alpha1_model_spec.py b/python/kfserving/test/test_v1alpha1_model_spec.py new file mode 100644 index 00000000000..2295961fb50 --- /dev/null +++ b/python/kfserving/test/test_v1alpha1_model_spec.py @@ -0,0 +1,70 @@ +# Copyright 2020 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# coding: utf-8 + +""" + KFServing + + Python SDK for KFServing # noqa: E501 + + The version of the OpenAPI document: v0.1 + Generated by: https://openapi-generator.tech +""" + + +from __future__ import absolute_import + +import unittest +import datetime + +import kfserving +from kfserving.models.v1alpha1_model_spec import V1alpha1ModelSpec # noqa: E501 +from kfserving.rest import ApiException + +class TestV1alpha1ModelSpec(unittest.TestCase): + """V1alpha1ModelSpec unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional): + """Test V1alpha1ModelSpec + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # model = kfserving.models.v1alpha1_model_spec.V1alpha1ModelSpec() # noqa: E501 + if include_optional : + return V1alpha1ModelSpec( + framework = '0', + memory = None, + storage_uri = '0' + ) + else : + return V1alpha1ModelSpec( + framework = '0', + storage_uri = '0', + ) + + def testV1alpha1ModelSpec(self): + """Test V1alpha1ModelSpec""" + inst_req_only = self.make_instance(include_optional=False) + inst_req_and_optional = self.make_instance(include_optional=True) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/kfserving/test/test_v1alpha1_trained_model_spec.py b/python/kfserving/test/test_v1alpha1_trained_model_spec.py new file mode 100644 index 00000000000..feca320e2b3 --- /dev/null +++ b/python/kfserving/test/test_v1alpha1_trained_model_spec.py @@ -0,0 +1,81 @@ +# Copyright 2020 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# coding: utf-8 + +""" + KFServing + + Python SDK for KFServing # noqa: E501 + + The version of the OpenAPI document: v0.1 + Generated by: https://openapi-generator.tech +""" + + +from __future__ import absolute_import + +import unittest +import datetime + +import kfserving +from kfserving.models.v1alpha1_trained_model_spec import V1alpha1TrainedModelSpec # noqa: E501 +from kfserving.rest import ApiException + +class TestV1alpha1TrainedModelSpec(unittest.TestCase): + """V1alpha1TrainedModelSpec unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional): + """Test V1alpha1TrainedModelSpec + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # model = kfserving.models.v1alpha1_trained_model_spec.V1alpha1TrainedModelSpec() # noqa: E501 + if include_optional : + return V1alpha1TrainedModelSpec( + inference_service = '0', + model = kfserving.models.v1alpha1_trained_model.V1alpha1TrainedModel( + api_version = '0', + kind = '0', + metadata = None, + spec = None, + status = None + ) + ) + else : + return V1alpha1TrainedModelSpec( + inference_service = '0', + model = kfserving.models.v1alpha1_trained_model.V1alpha1TrainedModel( + api_version = '0', + kind = '0', + metadata = None, + spec = None, + status = None + ) + ) + + def testV1alpha1TrainedModelSpec(self): + """Test V1alpha1TrainedModelSpec""" + inst_req_only = self.make_instance(include_optional=False) + inst_req_and_optional = self.make_instance(include_optional=True) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/kfserving/test/test_v1beta1_component_status_spec.py b/python/kfserving/test/test_v1beta1_component_status_spec.py index 0607973085d..ac41835df12 100644 --- a/python/kfserving/test/test_v1beta1_component_status_spec.py +++ b/python/kfserving/test/test_v1beta1_component_status_spec.py @@ -51,10 +51,11 @@ def make_instance(self, include_optional): if include_optional : return V1beta1ComponentStatusSpec( address = None, - latest_created_revision = '0', + latest_created_revision = '0', latest_ready_revision = '0', - previous_ready_revision = '0', - traffic_percent = 56, + latest_rolledout_revision = '0', + previous_rolledout_revision = '0', + traffic = list(), url = None ) else : diff --git a/python/kfserving/test/test_v1beta1_inference_service.py b/python/kfserving/test/test_v1beta1_inference_service.py index c675004d604..ece2e87049b 100644 --- a/python/kfserving/test/test_v1beta1_inference_service.py +++ b/python/kfserving/test/test_v1beta1_inference_service.py @@ -358,9 +358,10 @@ def make_instance(self, include_optional): 'key' : kfserving.models.v1beta1_component_status_spec.V1beta1ComponentStatusSpec( address = None, latest_created_revision = '0', - latest_ready_revision = '0', - previous_ready_revision = '0', - traffic_percent = 56, + latest_ready_revision = '0', + latest_rolledout_revision = '0', + previous_rolledout_revision = '0', + traffic = list(), url = None, ) }, conditions = [ diff --git a/python/kfserving/test/test_v1beta1_inference_service_list.py b/python/kfserving/test/test_v1beta1_inference_service_list.py index d892c395b31..d85c559c04c 100644 --- a/python/kfserving/test/test_v1beta1_inference_service_list.py +++ b/python/kfserving/test/test_v1beta1_inference_service_list.py @@ -362,8 +362,9 @@ def make_instance(self, include_optional): address = None, latest_created_revision = '0', latest_ready_revision = '0', - previous_ready_revision = '0', - traffic_percent = 56, + latest_rolledout_revision = '0', + previous_rolledout_revision = '0', + traffic = list(), url = None, ) }, conditions = [ @@ -687,9 +688,10 @@ def make_instance(self, include_optional): 'key' : kfserving.models.v1beta1_component_status_spec.V1beta1ComponentStatusSpec( address = None, latest_created_revision = '0', - latest_ready_revision = '0', - previous_ready_revision = '0', - traffic_percent = 56, + latest_ready_revision = '0', + latest_rolledout_revision = '0', + previous_rolledout_revision = '0', + traffic = list(), url = None, ) }, conditions = [ diff --git a/python/kfserving/test/test_v1beta1_inference_service_status.py b/python/kfserving/test/test_v1beta1_inference_service_status.py index a5487311c07..13d519f9da1 100644 --- a/python/kfserving/test/test_v1beta1_inference_service_status.py +++ b/python/kfserving/test/test_v1beta1_inference_service_status.py @@ -56,8 +56,9 @@ def make_instance(self, include_optional): address = None, latest_created_revision = '0', latest_ready_revision = '0', - previous_ready_revision = '0', - traffic_percent = 56, + latest_rolledout_revision = '0', + previous_rolledout_revision = '0', + traffic = list(), url = None, ) }, conditions = [