From 11f01edc4f307c4e8421090aafb2b054bfa28b3c Mon Sep 17 00:00:00 2001 From: Christian Vogt Date: Wed, 10 Jul 2024 13:54:35 -0400 Subject: [PATCH] refactor model registry proxy onto proxy util --- .../routes/api/service/modelregistry/index.ts | 48 ++++------ backend/src/utils/proxy.ts | 91 ++++++++++--------- 2 files changed, 67 insertions(+), 72 deletions(-) diff --git a/backend/src/routes/api/service/modelregistry/index.ts b/backend/src/routes/api/service/modelregistry/index.ts index b214d3055b..b44e78bb82 100644 --- a/backend/src/routes/api/service/modelregistry/index.ts +++ b/backend/src/routes/api/service/modelregistry/index.ts @@ -1,32 +1,18 @@ -import httpProxy from '@fastify/http-proxy'; -import { KubeFastifyInstance } from '../../../../types'; -import { DEV_MODE, MODEL_REGISTRY_NAMESPACE } from '../../../../utils/constants'; -import { getParam, setParam } from '../../../../utils/proxy'; +import { MODEL_REGISTRY_NAMESPACE } from '../../../../utils/constants'; +import { proxyService } from '../../../../utils/proxy'; -export default async (fastify: KubeFastifyInstance): Promise => { - fastify.register(httpProxy, { - upstream: '', - prefix: '/:name', - rewritePrefix: '', - replyOptions: { - // preHandler must set the `upstream` param - getUpstream: (request) => getParam(request, 'upstream'), - }, - preHandler: (request, _, done) => { - const name = getParam(request, 'name'); - - const upstream = DEV_MODE - ? // Use port forwarding for local development: - // kubectl port-forward -n svc/ : - `http://${process.env.MODEL_REGISTRY_SERVICE_HOST}:${process.env.MODEL_REGISTRY_SERVICE_PORT}` - : // Construct service URL - `http://${name}.${MODEL_REGISTRY_NAMESPACE}.svc.cluster.local:8080`; - - // assign the `upstream` param so we can dynamically set the upstream URL for http-proxy - setParam(request, 'upstream', upstream); - - fastify.log.info(`Proxy ${request.method} request ${request.url} to ${upstream}`); - done(); - }, - }); -}; +export default proxyService( + null, + { + port: 8080, + namespace: MODEL_REGISTRY_NAMESPACE, + }, + { + // Use port forwarding for local development: + // kubectl port-forward -n odh-model-registries svc/ 8085:8080 + host: process.env.MODEL_REGISTRY_SERVICE_HOST, + port: process.env.MODEL_REGISTRY_SERVICE_PORT, + }, + null, + false, +); diff --git a/backend/src/utils/proxy.ts b/backend/src/utils/proxy.ts index 53c6347d41..394f152db2 100644 --- a/backend/src/utils/proxy.ts +++ b/backend/src/utils/proxy.ts @@ -27,12 +27,13 @@ const notFoundError = (kind: string, name: string, e?: any, overrideMessage?: st }; export const proxyService = - ( - model: { apiGroup: string; apiVersion: string; plural: string; kind: string }, + ( + model: { apiGroup: string; apiVersion: string; plural: string; kind: string } | null, service: { port: number | string; prefix?: string; suffix?: string; + namespace?: string; }, local: { host: string; @@ -44,7 +45,7 @@ export const proxyService = async (fastify: KubeFastifyInstance): Promise => { fastify.register(httpProxy, { upstream: '', - prefix: '/:namespace/:name', + prefix: service.namespace ? ':name' : '/:namespace/:name', rewritePrefix: '', replyOptions: { // preHandler must set the `upstream` param @@ -65,52 +66,60 @@ export const proxyService = ); return; } - const kc = fastify.kube.config; - const cluster = kc.getCurrentCluster(); - // see `prefix` for named params - const namespace = getParam(request, 'namespace'); + const namespace = service.namespace ?? getParam(request, 'namespace'); const name = getParam(request, 'name'); - // retreive the gating resource by name and namespace - passThroughResource(fastify, request, { - url: `${cluster.server}/apis/${model.apiGroup}/${model.apiVersion}/namespaces/${namespace}/${model.plural}/${name}`, - method: 'GET', - }) - .then((resource) => { - return getDirectCallOptions(fastify, request, request.url).then((requestOptions) => { - if (isK8sStatus(resource)) { - done(notFoundError(model.kind, name)); - } else if (!statusCheck || statusCheck(resource)) { - if (tls) { - const token = getAccessToken(requestOptions); - request.headers.authorization = `Bearer ${token}`; - } + const doServiceRequest = () => { + const scheme = tls ? 'https' : 'http'; - const scheme = tls ? 'https' : 'http'; + const upstream = DEV_MODE + ? // Use port forwarding for local development: + // kubectl port-forward -n svc/ : + `${scheme}://${local.host}:${local.port}` + : // Construct service URL + `${scheme}://${service.prefix || ''}${name}${ + service.suffix ?? '' + }.${namespace}.svc.cluster.local:${service.port}`; - const upstream = DEV_MODE - ? // Use port forwarding for local development: - // kubectl port-forward -n svc/ : - `${scheme}://${local.host}:${local.port}` - : // Construct service URL - `${scheme}://${service?.prefix || ''}${resource.metadata.name}${ - service?.suffix ?? '' - }.${resource.metadata.namespace}.svc.cluster.local:${service.port}`; + // assign the `upstream` param so we can dynamically set the upstream URL for http-proxy + setParam(request, 'upstream', upstream); - // assign the `upstream` param so we can dynamically set the upstream URL for http-proxy - setParam(request, 'upstream', upstream); + fastify.log.info(`Proxy ${request.method} request ${request.url} to ${upstream}`); + done(); + }; - fastify.log.info(`Proxy ${request.method} request ${request.url} to ${upstream}`); - done(); - } else { - done(notFoundError(model.kind, name, undefined, 'service unavailable')); - } - }); + if (model) { + const kc = fastify.kube.config; + const cluster = kc.getCurrentCluster(); + + // retreive the gating resource by name and namespace + passThroughResource(fastify, request, { + url: `${cluster.server}/apis/${model.apiGroup}/${model.apiVersion}/namespaces/${namespace}/${model.plural}/${name}`, + method: 'GET', }) - .catch((e) => { - done(notFoundError(model.kind, name, e)); - }); + .then((resource) => { + return getDirectCallOptions(fastify, request, request.url).then((requestOptions) => { + if (isK8sStatus(resource)) { + done(notFoundError(model.kind, name)); + } else if (!statusCheck || statusCheck(resource)) { + if (tls) { + const token = getAccessToken(requestOptions); + request.headers.authorization = `Bearer ${token}`; + } + + doServiceRequest(); + } else { + done(notFoundError(model.kind, name, undefined, 'service unavailable')); + } + }); + }) + .catch((e) => { + done(notFoundError(model.kind, name, e)); + }); + } else { + doServiceRequest(); + } }, }); };