def grafana_proxy_model_endpoints_check_connection(request: Request): """ Root of grafana proxy for the model-endpoints API, used for validating the model-endpoints data source connectivity. """ get_access_key(request) return Response(status_code=HTTPStatus.OK.value)
def clear_endpoint_record(request: Request, project: str, endpoint_id: str): """ Clears endpoint record from KV by endpoint_id """ access_key = get_access_key(request) ModelEndpoints.clear_endpoint_record(access_key, project, endpoint_id) return Response(status_code=HTTPStatus.NO_CONTENT.value)
def create_or_patch( request: Request, project: str, endpoint_id: str, model_endpoint: ModelEndpoint, auth_verifier: mlrun.api.api.deps.AuthVerifier = Depends( mlrun.api.api.deps.AuthVerifier), db_session: Session = Depends(mlrun.api.api.deps.get_db_session), ) -> Response: """ Either create or updates the kv record of a given ModelEndpoint object """ access_key = get_access_key(request.headers) if project != model_endpoint.metadata.project: raise MLRunConflictError( f"Can't store endpoint of project {model_endpoint.metadata.project} into project {project}" ) if endpoint_id != model_endpoint.metadata.uid: raise MLRunConflictError( f"Mismatch between endpoint_id {endpoint_id} and ModelEndpoint.metadata.uid {model_endpoint.metadata.uid}." f"\nMake sure the supplied function_uri, and model are configured as intended" ) ModelEndpoints.create_or_patch( db_session=db_session, access_key=access_key, model_endpoint=model_endpoint, leader_session=auth_verifier.auth_info.session, ) return Response(status_code=HTTPStatus.NO_CONTENT.value)
async def delete_endpoint_record(request: Request, project: str, endpoint_id: str) -> Response: """ Clears endpoint record from KV by endpoint_id """ access_key = get_access_key(request.headers) await ModelEndpoints.delete_endpoint_record(access_key=access_key, project=project, endpoint_id=endpoint_id) return Response(status_code=HTTPStatus.NO_CONTENT.value)
async def grafana_proxy_model_endpoints_search( request: Request, db_session: Session = Depends(deps.get_db_session), ) -> List[str]: """ Search route for model-endpoints grafana proxy API, used for creating an interface between grafana queries and model-endpoints logic. This implementation requires passing target_endpoint query parameter in order to dispatch different model-endpoint monitoring functions. """ get_access_key(request.headers) body = await request.json() query_parameters = _parse_search_parameters(body) _validate_query_parameters(query_parameters, SUPPORTED_SEARCH_FUNCTIONS) # At this point everything is validated and we can access everything that is needed without performing all previous # checks again. target_endpoint = query_parameters["target_endpoint"] function = NAME_TO_SEARCH_FUNCTION_DICTIONARY[target_endpoint] result = await run_in_threadpool(function, db_session) return result
async def create_or_patch(request: Request, project: str, endpoint_id: str, model_endpoint: ModelEndpoint) -> Response: """ Either create or updates the kv record of a given ModelEndpoint object """ access_key = get_access_key(request.headers) if project != model_endpoint.metadata.project: raise MLRunConflictError( f"Can't store endpoint of project {model_endpoint.metadata.project} into project {project}" ) if endpoint_id != model_endpoint.metadata.uid: raise MLRunConflictError( f"Mismatch between endpoint_id {endpoint_id} and ModelEndpoint.metadata.uid {model_endpoint.metadata.uid}." f"\nMake sure the supplied function_uri, and model are configured as intended" ) await ModelEndpoints.create_or_patch(access_key=access_key, model_endpoint=model_endpoint) return Response(status_code=HTTPStatus.NO_CONTENT.value)
def get_endpoint( request: Request, project: str, endpoint_id: str, start: str = Query(default="now-1h"), end: str = Query(default="now"), metrics: List[str] = Query([], alias="metric"), features: bool = Query(default=False), ): access_key = get_access_key(request) return ModelEndpoints.get_endpoint( access_key=access_key, project=project, endpoint_id=endpoint_id, metrics=metrics, start=start, end=end, features=features, )
async def get_endpoint( request: Request, project: str, endpoint_id: str, start: str = Query(default="now-1h"), end: str = Query(default="now"), metrics: List[str] = Query([], alias="metric"), feature_analysis: bool = Query(default=False), ) -> ModelEndpoint: access_key = get_access_key(request.headers) endpoint = await ModelEndpoints.get_endpoint( access_key=access_key, project=project, endpoint_id=endpoint_id, metrics=metrics, start=start, end=end, feature_analysis=feature_analysis, ) return endpoint
async def grafana_proxy_model_endpoints_query( request: Request) -> List[GrafanaTable]: """ Query route for model-endpoints grafana proxy API, used for creating an interface between grafana queries and model-endpoints logic. This implementation requires passing `target_function` query parameter in order to dispatch different model-endpoint monitoring functions. """ access_key = get_access_key(request) body = await request.json() query_parameters = _parse_query_parameters(body) _validate_query_parameters(query_parameters) # At this point everything is validated and we can access everything that is needed without performing all previous # checks again. target_endpoint = query_parameters["target_endpoint"] result = NAME_TO_FUNCTION_DICTIONARY[target_endpoint](body, query_parameters, access_key) return result
async def grafana_proxy_model_endpoints_query( request: Request, ) -> List[Union[GrafanaTable, GrafanaTimeSeriesTarget]]: """ Query route for model-endpoints grafana proxy API, used for creating an interface between grafana queries and model-endpoints logic. This implementation requires passing target_endpoint query parameter in order to dispatch different model-endpoint monitoring functions. """ access_key = get_access_key(request.headers) body = await request.json() query_parameters = _parse_query_parameters(body) _validate_query_parameters(query_parameters, SUPPORTED_QUERY_FUNCTIONS) query_parameters = _drop_grafana_escape_chars(query_parameters) # At this point everything is validated and we can access everything that is needed without performing all previous # checks again. target_endpoint = query_parameters["target_endpoint"] function = NAME_TO_QUERY_FUNCTION_DICTIONARY[target_endpoint] result = await run_in_threadpool(function, body, query_parameters, access_key) return result
def list_endpoints( request: Request, project: str, model: Optional[str] = Query(None), function: Optional[str] = Query(None), tag: Optional[str] = Query(None), labels: List[str] = Query([], alias="label"), start: str = Query(default="now-1h"), end: str = Query(default="now"), metrics: List[str] = Query([], alias="metric"), ): """ Returns a list of endpoints of type 'ModelEndpoint', supports filtering by model, function, tag and labels. Lables can be used to filter on the existance of a label: `api/projects/{project}/model-endpoints/?label=mylabel` Or on the value of a given label: `api/projects/{project}/model-endpoints/?label=mylabel=1` Multiple labels can be queried in a single request by either using `&` seperator: `api/projects/{project}/model-endpoints/?label=mylabel=1&label=myotherlabel=2` Or by using a `,` (comma) seperator: `api/projects/{project}/model-endpoints/?label=mylabel=1,myotherlabel=2` """ access_key = get_access_key(request) endpoint_list = ModelEndpoints.list_endpoints( access_key=access_key, project=project, model=model, function=function, tag=tag, labels=labels, metrics=metrics, start=start, end=end, ) return ModelEndpointStateList(endpoints=endpoint_list)
def list_endpoints( request: Request, project: str, model: Optional[str] = Query(None), function: Optional[str] = Query(None), labels: List[str] = Query([], alias="label"), start: str = Query(default="now-1h"), end: str = Query(default="now"), metrics: List[str] = Query([], alias="metric"), ) -> ModelEndpointList: """ Returns a list of endpoints of type 'ModelEndpoint', supports filtering by model, function, tag and labels. Labels can be used to filter on the existence of a label: api/projects/{project}/model-endpoints/?label=mylabel Or on the value of a given label: api/projects/{project}/model-endpoints/?label=mylabel=1 Multiple labels can be queried in a single request by either using "&" separator: api/projects/{project}/model-endpoints/?label=mylabel=1&label=myotherlabel=2 Or by using a "," (comma) separator: api/projects/{project}/model-endpoints/?label=mylabel=1,myotherlabel=2 """ access_key = get_access_key(request.headers) endpoints = ModelEndpoints.list_endpoints( access_key=access_key, project=project, model=model, function=function, labels=labels, metrics=metrics, start=start, end=end, ) return endpoints
def test_get_access_key(): key = get_access_key({"X-V3io-Session-Key": "asd"}) assert key == "asd" with pytest.raises(MLRunBadRequestError): get_access_key({"some_other_header": "asd"})