def update_deployment(self, name, model_uri=None, flavor=None, config=None): """Updates an existing model deployment in openshift. It can either update the `model_uri` and/or the mandatory config items describing the container image, i.e `image`, `docker_registry`, `tag`. Notes: In case more configurations need to be changed, consider deleting and creating the deployment from scratch. Special treatment for different model flavors are not implemented. Args: name (str): name of the deployment model_uri (str): path where to find the mlflow packed model flavor (str, optional): mlflow deployment flavor. Defaults to None config (dict, optional): config items for the deployment. Defaults to {} Raises: MlflowException: if the updated deployment lead to an error in openshift Returns: dict: {'name': <name>, 'flavor': <flavor>} """ if not model_uri and not config: raise MlflowException( "Provide at least a new *model_uri* or *config*") dc_obj = oc.selector("dc", labels={"app": name}).object() if config: if all(key in config for key in ("image", "docker_registry", "tag")): dc_obj = oc_helper.update_container_image(dc_obj, config) else: raise MlflowException( "Not all of the necessary *config* items for updating are provided. " "You need to provide: image, docker_registry, tag, auth_user and auth_password" ) if model_uri: dc_obj = oc_helper.update_model_uri(dc_obj, model_uri) # hotfix for bug in openshift-client library -> normal apply() dc_obj.modify_and_apply(lambda x: True, retries=0) route_host = oc_helper.get_route_name(name) auth_user, auth_password = oc_helper.get_authentication_info(name) try: oc_helper.check_succesful_deployment(name, route_host, auth_user, auth_password) except MlflowException as mlflow_exception: self.delete_deployment(name) raise mlflow_exception return {'name': name, 'flavor': flavor}
def create_deployment(self, name, model_uri, flavor=None, config={}): """Creates all necessary artifacts for a model deployment in openshift. Notes: special treatment for different model flavors are not implemented. Args: name (str): name of the deployment model_uri (str): path where to find the mlflow packed model flavor (str, optional): mlflow deployment flavor. Defaults to None config (dict, optional): config items for the deployment. Defaults to {} Necessary config items: image, docker_registry, tag Raises: mlflow_exception: if the deployment failed in openshift or not all mandatory config items are provided Returns: dict: {'name': <name>, 'flavor': <flavor>} """ if not all(key in config for key in ("image", "docker_registry", "tag")): raise MlflowException( "not all mandatory config items (image, docker_registry, tag) " "are provided.") config = set_config_defaults(config) template_path = os.path.join(os.path.dirname(__file__), 'templates/deploy_with_auth.yml') config["NAME"] = name config["MODEL_URI"] = model_uri oc_helper.apply_deployment_config(config, template_path) try: route_host = oc_helper.get_route_name(name) oc_helper.check_succesful_deployment(name, route_host, config["BASIC_AUTH_USERNAME"], config["BASIC_AUTH_PASSWORD"]) except MlflowException as mlflow_exception: self.delete_deployment(name) raise mlflow_exception logger.info("\n" + "Endpoint available under: " + route_host) return {'name': name, 'flavor': flavor}
def predict(self, deployment_name, df): """Makes predictions using the specified deployment name. This can be used for making batch predictions using the openshift infrastrucutre, e.g. in automated daily/weekly pipelines. Args: deployment_name (str): name of the deployment df (pd.DataFrame): dataframe with the correct format the model expects Returns: np.ndarray: array containing the predictions """ auth_user, auth_password = oc_helper.get_authentication_info( deployment_name) route_host = oc_helper.get_route_name(deployment_name) # send to https model deployment payload = df.to_dict(orient='split') response = requests.post("https://{0}/invocations".format(route_host), headers={'Content-Type': 'application/json'}, auth=(auth_user, auth_password), data=json.dumps(payload)) list_response = ast.literal_eval(response.content.decode("utf-8")) return np.array(list_response)