Beispiel #1
0
    def create(cluster: Cluster, name: str, modelversion_id: int,
               config: MetricSpecConfig) -> 'MetricSpec':
        """
        Create MetricSpec and returns corresponding instance.

        :param cluster: active cluster
        :param name: name of the metric
        :param modelversion_id: ModelVersion for which to create a MetricSpec
        :param config: MetricSpecConfig, describing MetricSpec
        :return: metricSpec
        """
        metric_spec_json = {
            'name': name,
            'modelVersionId': modelversion_id,
            'config': {
                'modelVersionId': config.modelversion_id,
                'threshold': config.threshold,
                'thresholdCmpOperator': {
                    'kind': config.threshold_op
                }
            }
        }
        resp = cluster.request("POST",
                               MetricSpec._BASE_URL,
                               json=metric_spec_json)
        handle_request_error(
            resp,
            f"Failed to create a MetricSpec for name={name}, modelversion_id={modelversion_id}. {resp.status_code} {resp.text}"
        )
        return MetricSpec._from_json(cluster, resp.json())
    def build(self, cluster: Cluster) -> Application:
        """
        Create an Application in your Hydrosphere cluster.

        :return: Application object
        """
        if not self.stages:
            raise ValueError("No execution stages were provided")

        execution_graph = ExecutionGraph(stages=self.stages)
        application_json = {
            "name": self.name,
            "kafkaStreaming":
            [sp.to_dict() for sp in self.streaming_parameters],
            "executionGraph": execution_graph.to_dict(),
            "metadata": self.metadata
        }

        resp = cluster.request("POST",
                               Application._BASE_URL,
                               json=application_json)
        handle_request_error(
            resp,
            f"Failed to create an application {self.name}. {resp.status_code} {resp.text}"
        )
        return Application._from_json(cluster, resp.json())
Beispiel #3
0
    def create(
        cluster: Cluster,
        model_name: str,
        version: int,
        metadata: Optional[Dict[str, str]] = None,
        deployment_configuration: Optional[DeploymentConfiguration] = None
    ) -> 'Servable':
        """
        Deploy an instance of uploaded model version at your cluster.

        :param deployment_configuration: k8s configurations used to run this servable
        :param cluster: Cluster connected to Hydrosphere
        :param model_name: Name of uploaded model
        :param version: Version of uploaded model
        :param metadata: Information which you can attach to your servable in a form of Dict[str, str]
        :raises ServableException:
        :return: servable
        """
        msg = {
            "modelName": model_name,
            "version": version,
        }
        if metadata:
            msg['metadata'] = metadata

        if deployment_configuration:
            msg['deploymentConfigName'] = deployment_configuration.name

        resp = cluster.request('POST', Servable._BASE_URL, json=msg)
        handle_request_error(
            resp,
            f"Failed to create a servable. {resp.status_code} {resp.text}")
        return Servable._from_json(cluster, resp.json())
def test_training_data_upload(cluster: Cluster,
                              model_version_builder: ModelVersionBuilder,
                              training_data: str):
    mv: ModelVersion = model_version_builder.build(cluster)
    mv.training_data = training_data
    data_upload_response = mv.upload_training_data()
    data_upload_response.wait(sleep=5)
    resp = cluster.request("GET", f"/monitoring/profiles/batch/{mv.id}/status")
    assert "Success" == resp.json()["kind"]
    def list(cluster: Cluster) -> List['DeploymentConfiguration']:
        """
        List all deployment configurations

        :param cluster:
        :return:
        """
        resp = cluster.request("GET", DeploymentConfiguration._BASE_URL)
        handle_request_error(resp, f"Failed to get a list of Deployment Configurations - {resp.status_code} {resp.text}")
        return [DeploymentConfiguration.parse_obj(app_json) for app_json in resp.json()]
def _upload_s3_file(cluster: Cluster, modelversion_id: int, path: str) -> requests.Response:
    """
    Internal method for submitting training data from S3 to Hydrosphere.

    :param cluster: Cluster instance
    :param url: url to which submit S3 path
    :param path: S3 path to training data
    """
    url = f'/monitoring/profiles/batch/{modelversion_id}/s3'
    return cluster.request("POST", url, json={"path": path})
    def find(cluster: Cluster, name: str) -> 'DeploymentConfiguration':
        """
        Search a deployment configuration by name

        :param cluster:
        :param name:
        :return:
        """
        resp = cluster.request("GET", f"{DeploymentConfiguration._BASE_URL}/{name}")
        handle_request_error(resp, f"Failed to find Deployment Configuration named {name} {resp.status_code} {resp.text}")
        return DeploymentConfiguration.parse_obj(resp.json())
    def delete(cluster: Cluster, name: str) -> dict:
        """
        Delete deployment configuration from Hydrosphere cluster

        :param cluster: Active Cluster
        :param name: Deployment configuration name
        :return: json response from the server
        """
        resp = cluster.request("DELETE", f"{DeploymentConfiguration._BASE_URL}/{name}")
        handle_request_error(resp, f"Failed to delete Deployment Configuration named {name}: {resp.status_code} {resp.text}")
        return resp
Beispiel #9
0
    def list(cluster: Cluster) -> List['MetricSpec']:
        """
        Send request and returns list with all available metric specs.

        :param cluster: active cluster
        :return: list with all available metric specs
        """
        resp = cluster.request("GET", MetricSpec._BASE_URL)
        handle_request_error(
            resp,
            f"Failed to list MetricSpecs. {resp.status_code} {resp.text}")
        return [MetricSpec._from_json(cluster, x) for x in resp.json()]
Beispiel #10
0
    def delete(cluster: Cluster, id: int) -> dict:
        """
        Delete MetricSpec.

        :return: result of deletion
        """
        resp = cluster.request("DELETE", f"{MetricSpec._BASE_URL}/{id}")
        handle_request_error(
            resp,
            f"Failed to delete MetricSpec for id={id}. {resp.status_code} {resp.text}"
        )
        return resp.json()
def _upload_local_file(cluster: Cluster, modelversion_id: int, path: str, 
                       chunk_size=1024) -> requests.Response:
    """
    Internal method for uploading local training data to Hydrosphere.

    :param cluster: active cluster
    :param modelversion_id: modelversion_id for which to upload training data
    :param path: path to a local file
    :param chunk_size: chunk size to use for streaming
    """    
    gen = read_in_chunks(path, chunk_size)
    url = f'/monitoring/profiles/batch/{modelversion_id}'
    return cluster.request("POST", url, data=gen, stream=True)
    def find(cluster: Cluster, name: str, version: int) -> 'ModelVersion':
        """
        Find a ModelVersion on the cluster by model name and a version.

        :param cluster: active cluster
        :param name: name of the model
        :param version: version of the model
        :return: ModelVersion object
        """
        resp = cluster.request("GET", f"{ModelVersion._BASE_URL}/version/{name}/{version}")
        handle_request_error(
            resp, f"Failed to find model_version for name={name}, version={version}. {resp.status_code} {resp.text}")
        return ModelVersion._from_json(cluster, resp.json())
    def list(cluster: Cluster) -> List['ModelVersion']:
        """
        List all model versions on the cluster.

        :param cluster: active cluster
        :return: list of ModelVersions 
        """

        resp = cluster.request("GET", f"{ModelVersion._BASE_URL}/version")
        handle_request_error(
            resp, f"Failed to list model versions. {resp.status_code} {resp.text}")
        return [ModelVersion._from_json(cluster, modelversion_json)
                for modelversion_json in resp.json()]
Beispiel #14
0
    def find_by_id(cluster: Cluster, id: int) -> 'MetricSpec':
        """
        Find MetricSpec by id.

        :param cluster: active cluster
        :param id: 
        :return: MetricSpec
        """
        resp = cluster.request("GET", f"{MetricSpec._BASE_URL}/{id}")
        handle_request_error(
            resp,
            f"Failed to retrieve MetricSpec for id={id}. {resp.status_code} {resp.text}"
        )
        return MetricSpec._from_json(cluster, resp.json())
Beispiel #15
0
    def list(cluster: Cluster) -> List['Servable']:
        """
        Retrieve a list of all servables available at your cluster

        :param cluster: Hydrosphere cluster
        :return: List of all Servables available at your cluster
        """
        resp = cluster.request("GET", Servable._BASE_URL)
        handle_request_error(
            resp, f"Failed to list servables. {resp.status_code} {resp.text}")
        return [
            Servable._from_json(cluster, servable_json)
            for servable_json in resp.json()
        ]
    def find(cluster: Cluster, application_name: str) -> 'Application':
        """
        Search for an application by name. 

        :param cluster: active cluster
        :param application_name: application name
        :return: deserialized application object
        """
        resp = cluster.request("GET",
                               f"{Application._BASE_URL}/{application_name}")
        handle_request_error(
            resp,
            f"Failed to find an application by name={application_name}. {resp.status_code} {resp.text}"
        )
        return Application._from_json(cluster, resp.json())
    def find_by_id(cluster: Cluster, id: int) -> 'ModelVersion':
        """
        Find a ModelVersion on the cluster by id.

        :param cluster: active cluster
        :param id: model version id
        :return: ModelVersion object
        """
        resp = cluster.request("GET", f"{ModelVersion._BASE_URL}/version")
        handle_request_error(
            resp, f"Failed to retrieve model_version by id={id}. {resp.status_code} {resp.text}")
        for modelversion_json in resp.json():
            if modelversion_json['id'] == id:
                return ModelVersion._from_json(cluster, modelversion_json)
        raise BadRequestException(f"Failed to retrieve model_version by id={id}.")
    def delete(cluster: Cluster, application_name: str) -> dict:
        """
        Delete an application by name.

        :param cluster: active cluster
        :param application_name: application name
        :return: response from the cluster
        """
        resp = cluster.request("DELETE",
                               f"{Application._BASE_URL}/{application_name}")
        handle_request_error(
            resp,
            f"Failed to delete application for name={application_name}. {resp.status_code} {resp.text}"
        )
        return resp.json()
Beispiel #19
0
    def find_by_name(cluster: Cluster, servable_name: str) -> 'Servable':
        """
        Finds a serving servable in a cluster

        :param cluster: active cluster
        :param servable_name: a name of the servable
        :raises ServableException:
        :return: Servable
        """

        resp = cluster.request("GET", f"{Servable._BASE_URL}/{servable_name}")
        handle_request_error(
            resp,
            f"Failed to find servable for name={servable_name}. {resp.status_code} {resp.text}"
        )
        return Servable._from_json(cluster, resp.json())
Beispiel #20
0
    def find_by_modelversion(cluster: Cluster,
                             modelversion_id: int) -> List['MetricSpec']:
        """
        Find MetricSpecs by model version.

        :param cluster: active cluster
        :param modelversion_id: ModelVersions for which to return metrics.
        :return: list of MetricSpec objects
        """
        resp = cluster.request(
            "GET", f"{MetricSpec._BASE_URL}/modelversion/{modelversion_id}")
        handle_request_error(
            resp,
            f"Failed to list MetricSpecs for modelversion_id={modelversion_id}. {resp.status_code} {resp.text}"
        )
        return [MetricSpec._from_json(cluster, x) for x in resp.json()]
    def list(cluster: Cluster) -> List['Application']:
        """
        List all available applications from the cluster.

        :param cluster: active cluster
        :return: deserialized list of application objects
        """
        resp = cluster.request("GET", Application._BASE_URL)
        handle_request_error(
            resp,
            f"Failed to list all applications. {resp.status_code} {resp.text}")
        applications = [
            Application._from_json(cluster, app_json)
            for app_json in resp.json()
        ]
        return applications
    def build(self, cluster: Cluster) -> DeploymentConfiguration:
        """
        Create the Deployment Configuration in your Hydrosphere cluster.

        :return: Deployment Configuration object from the Hydrosphere cluster
        """
        config = DeploymentConfiguration(
            name=self.name,
            hpa=self.hpa,
            pod=self.pod_spec,
            container=self.container_spec,
            deployment=self.deployment_spec
        )
        resp = cluster.request("POST", DeploymentConfiguration._BASE_URL, json=config.to_dict())
        handle_request_error(resp, f"Failed to upload new Deployment Configuration. {resp.status_code} {resp.text}")
        return DeploymentConfiguration.parse_obj(resp.json())
Beispiel #23
0
    def delete(cluster: Cluster, servable_name: str) -> dict:
        """
        Shut down and delete servable instance.

        :param cluster: active cluster
        :param servable_name: name of the servable
        :return: json response from serve

        .. warnings also::
          Use with caution. Predictors previously associated with this servable will not be able to connect to it.

        """
        resp = cluster.request("DELETE",
                               f"{Servable._BASE_URL}/{servable_name}")
        handle_request_error(
            resp,
            f"Failed to delete the servable with name={servable_name}. {resp.status_code} {resp.text}"
        )
        return resp.json()
    def build_external(self, cluster: Cluster) -> 'ModelVersion':
        """
        Create an external ModelVersion on the cluster. 

        :param cluster: active cluster
        :return: ModelVersion object
        """
        if self.signature is None:
            raise ValueError("signature is not specified for the model")
        model = {
            "name": self.name,
            "signature": ModelSignature_to_signature_dict(self.signature),
            "metadata": self.metadata
        }
        resp = cluster.request("POST", "/api/v2/externalmodel", json=model)
        handle_request_error(
            resp, f"Failed to create an external model. {resp.status_code} {resp.text}")
        json_dict = resp.json()
        json_dict['isExternal'] = True
        return ModelVersion._from_json(cluster, json_dict)
    def build(self, cluster: Cluster) -> 'ModelVersion':
        """
        Upload local model instance to the cluster.

        :param cluster: active cluster
        :return: ModelVersion object
        """
        if self.runtime is None:
            raise ValueError("runtime is not specified for the model")
        if self.signature is None:
            raise ValueError("signature is not specified for the model")

        meta = {
            "name": self.name,
            "runtime": self.runtime.dict(),
            "modelSignature": ModelSignature_to_signature_dict(self.signature),
            "installCommand": self.install_command,
            "metadata": self.metadata
        }
        
        if self.monitoring_configuration:
            meta.update({"monitoringConfiguration": self.monitoring_configuration.to_dict()})

        tarpath = self.__create_tarball()
        encoder = MultipartEncoder(
            fields={
                "payload": ("filename", open(tarpath, "rb")),
                "metadata": json.dumps(meta)
            }
        )
        
        resp = cluster.request("POST", "/api/v2/model/upload", 
            data=encoder, headers={'Content-Type': encoder.content_type})
        handle_request_error(
            resp, f"Failed to upload local model. {resp.status_code} {resp.text}")

        modelversion = ModelVersion._from_json(cluster, resp.json())
        modelversion.training_data = self.training_data
        return modelversion