diff --git a/package-lock.json b/package-lock.json index c06df90bc6..ad26602d07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3080,6 +3080,15 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" }, + "node_modules/@hapi/shot": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-6.0.1.tgz", + "integrity": "sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA==", + "dependencies": { + "@hapi/hoek": "^11.0.2", + "@hapi/validate": "^2.0.1" + } + }, "node_modules/@hapi/subtext": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.1.0.tgz", @@ -3120,6 +3129,23 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" }, + "node_modules/@hapi/validate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-2.0.1.tgz", + "integrity": "sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==", + "dependencies": { + "@hapi/hoek": "^11.0.2", + "@hapi/topo": "^6.0.1" + } + }, + "node_modules/@hapi/validate/node_modules/@hapi/topo": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", + "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } + }, "node_modules/@hapi/vise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz", @@ -34349,6 +34375,7 @@ "dependencies": { "@astronautlabs/jsonpath": "^1.1.0", "@hapi/call": "^9.0.1", + "@hapi/shot": "^6.0.1", "@hapi/subtext": "^7.1.0", "@k8slens/cluster-settings": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1", diff --git a/packages/core/package.json b/packages/core/package.json index b608493c38..ad9dd53c20 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -119,6 +119,7 @@ "dependencies": { "@astronautlabs/jsonpath": "^1.1.0", "@hapi/call": "^9.0.1", + "@hapi/shot": "^6.0.1", "@hapi/subtext": "^7.1.0", "@k8slens/cluster-settings": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1", diff --git a/packages/core/src/common/k8s-api/api-base.injectable.ts b/packages/core/src/common/k8s-api/api-base.injectable.ts index b340882672..d3a914f6a1 100644 --- a/packages/core/src/common/k8s-api/api-base.injectable.ts +++ b/packages/core/src/common/k8s-api/api-base.injectable.ts @@ -3,31 +3,27 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import lensFetchInjectable from "../fetch/lens-fetch.injectable"; +import loggerInjectable from "../logger.injectable"; import { apiPrefix } from "../vars"; -import isDebuggingInjectable from "../vars/is-debugging.injectable"; -import isDevelopmentInjectable from "../vars/is-development.injectable"; import { apiBaseHostHeaderInjectionToken, apiBaseServerAddressInjectionToken } from "./api-base-configs"; -import createJsonApiInjectable from "./create-json-api.injectable"; +import isApiBaseInDebugModeInjectable from "./is-api-in-debug-mode.injectable"; +import { JsonApi } from "./json-api"; const apiBaseInjectable = getInjectable({ id: "api-base", - instantiate: (di) => { - const createJsonApi = di.inject(createJsonApiInjectable); - const isDebugging = di.inject(isDebuggingInjectable); - const isDevelopment = di.inject(isDevelopmentInjectable); - const serverAddress = di.inject(apiBaseServerAddressInjectionToken); - const hostHeaderValue = di.inject(apiBaseHostHeaderInjectionToken); - - return createJsonApi({ - serverAddress, - apiBase: apiPrefix, - debug: isDevelopment || isDebugging, - }, { - headers: { - "Host": hostHeaderValue, - }, - }); - }, + instantiate: (di) => new JsonApi({ + fetch: di.inject(lensFetchInjectable), + logger: di.inject(loggerInjectable), + }, { + serverAddress: di.inject(apiBaseServerAddressInjectionToken), + apiBase: apiPrefix, + debug: di.inject(isApiBaseInDebugModeInjectable), + }, { + headers: { + "Host": di.inject(apiBaseHostHeaderInjectionToken), + }, + }), }); export default apiBaseInjectable; diff --git a/packages/core/src/common/k8s-api/create-json-api.injectable.ts b/packages/core/src/common/k8s-api/create-json-api.injectable.ts index be5b49246d..7d945d136d 100644 --- a/packages/core/src/common/k8s-api/create-json-api.injectable.ts +++ b/packages/core/src/common/k8s-api/create-json-api.injectable.ts @@ -3,13 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { Agent } from "https"; import type { RequestInit } from "@k8slens/node-fetch"; -import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable"; import fetchInjectable from "../fetch/fetch.injectable"; import loggerInjectable from "../logger.injectable"; import type { JsonApiConfig, JsonApiData, JsonApiDependencies, JsonApiParams } from "./json-api"; import { JsonApi } from "./json-api"; +import lensAgentInjectable from "./lens-agent.injectable"; export type CreateJsonApi = = JsonApiParams>(config: JsonApiConfig, reqInit?: RequestInit) => JsonApi; @@ -20,20 +19,11 @@ const createJsonApiInjectable = getInjectable({ fetch: di.inject(fetchInjectable), logger: di.inject(loggerInjectable), }; - const lensProxyCert = di.inject(lensProxyCertificateInjectable); return (config, reqInit) => { - if (!config.getRequestOptions) { - config.getRequestOptions = async () => { - const agent = new Agent({ - ca: lensProxyCert.get().cert, - }); - - return { - agent, - }; - }; - } + config.getRequestOptions ??= async () => ({ + agent: di.inject(lensAgentInjectable), + }); return new JsonApi(deps, config, reqInit); }; diff --git a/packages/core/src/common/k8s-api/create-kube-json-api.injectable.ts b/packages/core/src/common/k8s-api/create-kube-json-api.injectable.ts index eb0a72cc5f..84883a5e43 100644 --- a/packages/core/src/common/k8s-api/create-kube-json-api.injectable.ts +++ b/packages/core/src/common/k8s-api/create-kube-json-api.injectable.ts @@ -3,13 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { Agent } from "https"; import type { RequestInit } from "@k8slens/node-fetch"; -import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable"; import fetchInjectable from "../fetch/fetch.injectable"; import loggerInjectable from "../logger.injectable"; import type { JsonApiConfig, JsonApiDependencies } from "./json-api"; import { KubeJsonApi } from "./kube-json-api"; +import lensAgentInjectable from "./lens-agent.injectable"; export type CreateKubeJsonApi = (config: JsonApiConfig, reqInit?: RequestInit) => KubeJsonApi; @@ -20,21 +19,12 @@ const createKubeJsonApiInjectable = getInjectable({ fetch: di.inject(fetchInjectable), logger: di.inject(loggerInjectable), }; - const lensProxyCert = di.inject(lensProxyCertificateInjectable); return (config, reqInit) => { - if (!config.getRequestOptions) { - config.getRequestOptions = async () => { - const agent = new Agent({ - ca: lensProxyCert.get().cert, - }); - - return { - agent, - }; - }; - } - + config.getRequestOptions ??= async () => ({ + agent: di.inject(lensAgentInjectable), + }); + return new KubeJsonApi(dependencies, config, reqInit); }; }, diff --git a/packages/core/src/common/k8s-api/is-api-in-debug-mode.injectable.ts b/packages/core/src/common/k8s-api/is-api-in-debug-mode.injectable.ts new file mode 100644 index 0000000000..2e18dde170 --- /dev/null +++ b/packages/core/src/common/k8s-api/is-api-in-debug-mode.injectable.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import isDebuggingInjectable from "../vars/is-debugging.injectable"; +import isDevelopmentInjectable from "../vars/is-development.injectable"; + +const isApiBaseInDebugModeInjectable = getInjectable({ + id: "is-api-base-in-debug-mode", + instantiate: (di) => di.inject(isDebuggingInjectable) || di.inject(isDevelopmentInjectable), +}); + +export default isApiBaseInDebugModeInjectable; diff --git a/packages/core/src/common/k8s-api/lens-agent.injectable.ts b/packages/core/src/common/k8s-api/lens-agent.injectable.ts new file mode 100644 index 0000000000..44f538d597 --- /dev/null +++ b/packages/core/src/common/k8s-api/lens-agent.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { Agent } from "https"; +import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable"; + +const lensAgentInjectable = getInjectable({ + id: "lens-agent", + instantiate: (di) => { + const lensProxyCert = di.inject(lensProxyCertificateInjectable); + + return new Agent({ + ca: lensProxyCert.get().cert, + }); + }, +}); + +export default lensAgentInjectable; diff --git a/packages/core/src/main/getDiForUnitTesting.ts b/packages/core/src/main/getDiForUnitTesting.ts index 83b3aa6d82..d5a07329ca 100644 --- a/packages/core/src/main/getDiForUnitTesting.ts +++ b/packages/core/src/main/getDiForUnitTesting.ts @@ -9,7 +9,6 @@ import { createContainer, isInjectable } from "@ogre-tools/injectable"; import spawnInjectable from "./child-process/spawn.injectable"; import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable"; import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable"; -import setupLensProxyInjectable from "./start-main-application/runnables/setup-lens-proxy.injectable"; import setupSyncingOfWeblinksInjectable from "../features/weblinks/main/setup-syncing-of-weblinks.injectable"; import setupDeepLinkingInjectable from "./electron-app/runnables/setup-deep-linking.injectable"; import setupMainWindowVisibilityAfterActivationInjectable from "./electron-app/runnables/setup-main-window-visibility-after-activation.injectable"; @@ -88,7 +87,6 @@ const overrideRunnablesHavingSideEffects = (di: DiContainer) => { initializeExtensionsInjectable, initializeClusterManagerInjectable, setupIpcMainHandlersInjectable, - setupLensProxyInjectable, setupSyncingOfWeblinksInjectable, ].forEach((injectable) => { di.override(injectable, () => ({ diff --git a/packages/core/src/main/lens-proxy/attempt-to-listen.injectable.ts b/packages/core/src/main/lens-proxy/attempt-to-listen.injectable.ts index 04a044252c..1455e9b1ac 100644 --- a/packages/core/src/main/lens-proxy/attempt-to-listen.injectable.ts +++ b/packages/core/src/main/lens-proxy/attempt-to-listen.injectable.ts @@ -3,7 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { AddressInfo } from "net"; import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable"; import loggerInjectable from "../../common/logger.injectable"; import lensProxyHttpsServerInjectable from "./https-proxy/server.injectable"; @@ -30,7 +29,7 @@ const attemptToListenInjectable = getInjectable({ .once("listening", () => { proxyServer.removeAllListeners("error"); // don't reject the promise - const { address, port } = proxyServer.address() as AddressInfo; + const { address, port } = proxyServer.address(); lensProxyPort.set(port); diff --git a/packages/core/src/main/lens-proxy/get-cluster-for-request.injectable.ts b/packages/core/src/main/lens-proxy/get-cluster-for-request.injectable.ts index 8be8d1d4e4..fcba6feb6d 100644 --- a/packages/core/src/main/lens-proxy/get-cluster-for-request.injectable.ts +++ b/packages/core/src/main/lens-proxy/get-cluster-for-request.injectable.ts @@ -3,10 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable"; +import type { Cluster } from "../../common/cluster/cluster"; import { getClusterIdFromHost } from "../../common/utils"; import { apiKubePrefix } from "../../common/vars"; -import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable"; -import type { GetClusterForRequest } from "./lens-proxy"; +import type { ProxyIncomingMessage } from "./messages"; + +export type GetClusterForRequest = (req: ProxyIncomingMessage) => Cluster | undefined; const getClusterForRequestInjectable = getInjectable({ id: "get-cluster-for-request", @@ -19,7 +22,7 @@ const getClusterForRequestInjectable = getInjectable({ } // lens-server is connecting to 127.0.0.1:/ - if (req.url && req.headers.host.startsWith("127.0.0.1")) { + if (req.headers.host.startsWith("127.0.0.1")) { const clusterId = req.url.split("/")[1]; const cluster = getClusterById(clusterId); diff --git a/packages/core/src/main/lens-proxy/handle-route-request.injectable.ts b/packages/core/src/main/lens-proxy/handle-route-request.injectable.ts index c156428a64..dc60aaad6a 100644 --- a/packages/core/src/main/lens-proxy/handle-route-request.injectable.ts +++ b/packages/core/src/main/lens-proxy/handle-route-request.injectable.ts @@ -6,12 +6,10 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ServerResponse } from "http"; import { apiKubePrefix } from "../../common/vars"; import contentSecurityPolicyInjectable from "../../common/vars/content-security-policy.injectable"; -import kubeAuthProxyServerInjectable from "../cluster/kube-auth-proxy-server.injectable"; import routeRequestInjectable from "../router/route-request.injectable"; import getClusterForRequestInjectable from "./get-cluster-for-request.injectable"; -import { isLongRunningRequest } from "./helpers"; import type { ProxyIncomingMessage } from "./messages"; -import rawHttpProxyInjectable from "./proxy/raw-proxy.injectable"; +import proxyReqToClusterInjectable from "./proxy/attempt.injectable"; export type HandleRouteRequest = (req: ProxyIncomingMessage, res: ServerResponse) => Promise; @@ -20,26 +18,18 @@ const handleRouteRequestInjectable = getInjectable({ instantiate: (di): HandleRouteRequest => { const getClusterForRequest = di.inject(getClusterForRequestInjectable); const routeRequest = di.inject(routeRequestInjectable); - const proxy = di.inject(rawHttpProxyInjectable); const contentSecurityPolicy = di.inject(contentSecurityPolicyInjectable); + const proxyReqToCluster = di.inject(proxyReqToClusterInjectable); return async (req, res) => { const cluster = getClusterForRequest(req); if (cluster && req.url.startsWith(apiKubePrefix)) { - delete req.headers.authorization; - req.url = req.url.replace(apiKubePrefix, ""); - - const kubeAuthProxyServer = di.inject(kubeAuthProxyServerInjectable, cluster); - const proxyTarget = await kubeAuthProxyServer.getApiTarget(isLongRunningRequest(req.url)); - - if (proxyTarget) { - return proxy.web(req, res, proxyTarget); - } + await proxyReqToCluster(cluster, req, res); + } else { + res.setHeader("Content-Security-Policy", contentSecurityPolicy); + await routeRequest(cluster, req, res); } - - res.setHeader("Content-Security-Policy", contentSecurityPolicy); - await routeRequest(cluster, req, res); }; }, }); diff --git a/packages/core/src/main/lens-proxy/https-proxy/server.global-override-for-injectable.ts b/packages/core/src/main/lens-proxy/https-proxy/server.global-override-for-injectable.ts new file mode 100644 index 0000000000..68b0c0f70c --- /dev/null +++ b/packages/core/src/main/lens-proxy/https-proxy/server.global-override-for-injectable.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getGlobalOverride } from "@k8slens/test-utils"; +import EventEmitter from "events"; +import lensProxyHttpsServerInjectable from "./server.injectable"; + +export default getGlobalOverride(lensProxyHttpsServerInjectable, () => new class extends EventEmitter { + close() { } + listen() { + this.emit("listening"); + } + address() { + return { + address: "https://localhost:9090", + port: 9090, + family: "some-family", + }; + } +}); diff --git a/packages/core/src/main/lens-proxy/https-proxy/server.injectable.ts b/packages/core/src/main/lens-proxy/https-proxy/server.injectable.ts index aefe4dbd26..59bc5cd82d 100644 --- a/packages/core/src/main/lens-proxy/https-proxy/server.injectable.ts +++ b/packages/core/src/main/lens-proxy/https-proxy/server.injectable.ts @@ -8,6 +8,20 @@ import lensProxyCertificateInjectable from "../../../common/certificate/lens-pro import handleRouteRequestInjectable from "../handle-route-request.injectable"; import lensProxyHttpsServerOnUpgradeInjectable from "./on-upgrade.injectable"; import { ProxyIncomingMessage } from "../messages"; +import type { AddressInfo } from "net"; + +export interface LensProxyHttpsServer { + close(): void; + listen(port: number, hostname: string): void; + once(event: "listening", listener: () => void): LensProxyHttpsServer; + once(event: "error", listener: (error: Error) => void): LensProxyHttpsServer; + on(event: "listening", listener: () => void): LensProxyHttpsServer; + on(event: "error", listener: (error: Error) => void): LensProxyHttpsServer; + off(event: "listening", listener: () => void): LensProxyHttpsServer; + off(event: "error", listener: (error: Error) => void): LensProxyHttpsServer; + removeAllListeners(event: "error" | "listening"): void; + address(): AddressInfo; +} const lensProxyHttpsServerInjectable = getInjectable({ id: "lens-proxy-https-server", @@ -23,8 +37,9 @@ const lensProxyHttpsServerInjectable = getInjectable({ server.on("upgrade", di.inject(lensProxyHttpsServerOnUpgradeInjectable)); - return server; + return server as LensProxyHttpsServer; }, + causesSideEffects: true, }); export default lensProxyHttpsServerInjectable; diff --git a/packages/core/src/main/lens-proxy/proxy-functions/index.ts b/packages/core/src/main/lens-proxy/proxy-functions/index.ts deleted file mode 100644 index 72553b2d2e..0000000000 --- a/packages/core/src/main/lens-proxy/proxy-functions/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -export * from "./types"; diff --git a/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts b/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts index d6ddfca49a..609b9998c8 100644 --- a/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts +++ b/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts @@ -9,9 +9,9 @@ import { connect } from "tls"; import url, { URL } from "url"; import { apiKubePrefix } from "../../../common/vars"; import { getInjectable } from "@ogre-tools/injectable"; -import type { LensProxyApiRequest } from "../lens-proxy"; import kubeAuthProxyServerInjectable from "../../cluster/kube-auth-proxy-server.injectable"; import kubeAuthProxyCertificateInjectable from "../../kube-auth-proxy/kube-auth-proxy-certificate.injectable"; +import type { LensProxyApiRequest } from "./types"; const skipRawHeaders = new Set(["Host", "Authorization"]); diff --git a/packages/core/src/main/lens-proxy/proxy-functions/shell-api-request.injectable.ts b/packages/core/src/main/lens-proxy/proxy-functions/shell-api-request.injectable.ts index afaf2a870d..b3f543f1cf 100644 --- a/packages/core/src/main/lens-proxy/proxy-functions/shell-api-request.injectable.ts +++ b/packages/core/src/main/lens-proxy/proxy-functions/shell-api-request.injectable.ts @@ -5,11 +5,11 @@ import { getInjectable } from "@ogre-tools/injectable"; import shellRequestAuthenticatorInjectable from "./shell-request-authenticator/shell-request-authenticator.injectable"; import openShellSessionInjectable from "../../shell-session/create-shell-session.injectable"; -import type { LensProxyApiRequest } from "../lens-proxy"; import URLParse from "url-parse"; import { Server as WebSocketServer } from "ws"; import loggerInjectable from "../../../common/logger.injectable"; import getClusterForRequestInjectable from "../get-cluster-for-request.injectable"; +import type { LensProxyApiRequest } from "./types"; const shellApiRequestInjectable = getInjectable({ id: "shell-api-request", diff --git a/packages/core/src/main/lens-proxy/proxy-functions/types.ts b/packages/core/src/main/lens-proxy/proxy-functions/types.ts index b6592ad244..e33037a229 100644 --- a/packages/core/src/main/lens-proxy/proxy-functions/types.ts +++ b/packages/core/src/main/lens-proxy/proxy-functions/types.ts @@ -3,14 +3,15 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type http from "http"; import type net from "net"; -import type { SetRequired } from "type-fest"; import type { Cluster } from "../../../common/cluster/cluster"; +import type { ProxyIncomingMessage } from "../messages"; export interface ProxyApiRequestArgs { - req: SetRequired; + req: ProxyIncomingMessage; socket: net.Socket; head: Buffer; cluster: Cluster; } + +export type LensProxyApiRequest = (args: ProxyApiRequestArgs) => void; diff --git a/packages/core/src/main/lens-proxy/proxy/attempt.global-override-for-injectable.ts b/packages/core/src/main/lens-proxy/proxy/attempt.global-override-for-injectable.ts new file mode 100644 index 0000000000..4e2a0ab9af --- /dev/null +++ b/packages/core/src/main/lens-proxy/proxy/attempt.global-override-for-injectable.ts @@ -0,0 +1,9 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; +import proxyReqToClusterInjectable from "./attempt.injectable"; + +export default getGlobalOverrideForFunction(proxyReqToClusterInjectable); diff --git a/packages/core/src/main/lens-proxy/proxy/attempt.injectable.ts b/packages/core/src/main/lens-proxy/proxy/attempt.injectable.ts new file mode 100644 index 0000000000..6d209ae7b5 --- /dev/null +++ b/packages/core/src/main/lens-proxy/proxy/attempt.injectable.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { ServerResponse } from "http"; +import type { Cluster } from "../../../common/cluster/cluster"; +import { apiKubePrefix } from "../../../common/vars"; +import kubeAuthProxyServerInjectable from "../../cluster/kube-auth-proxy-server.injectable"; +import { isLongRunningRequest } from "../helpers"; +import type { ProxyIncomingMessage } from "../messages"; +import rawHttpProxyInjectable from "./raw-proxy.injectable"; + +export type ProxyReqToCluster = (cluster: Cluster, req: ProxyIncomingMessage, res: ServerResponse) => Promise; + +const proxyReqToClusterInjectable = getInjectable({ + id: "proxy-req-to-cluster", + instantiate: (di): ProxyReqToCluster => { + const proxy = di.inject(rawHttpProxyInjectable); + + return async (cluster, req, res) => { + delete req.headers.authorization; + req.url = req.url.replace(apiKubePrefix, ""); + + const kubeAuthProxyServer = di.inject(kubeAuthProxyServerInjectable, cluster); + const proxyTarget = await kubeAuthProxyServer.getApiTarget(isLongRunningRequest(req.url)); + + proxy.web(req, res, proxyTarget); + }; + }, + causesSideEffects: true, +}); + +export default proxyReqToClusterInjectable; diff --git a/packages/core/src/main/lens-proxy/proxy/raw-proxy.injectable.ts b/packages/core/src/main/lens-proxy/proxy/raw-proxy.injectable.ts index 6f2489fe10..ca56658f6e 100644 --- a/packages/core/src/main/lens-proxy/proxy/raw-proxy.injectable.ts +++ b/packages/core/src/main/lens-proxy/proxy/raw-proxy.injectable.ts @@ -10,6 +10,7 @@ import type { ProxyIncomingMessage } from "../messages"; const rawHttpProxyInjectable = getInjectable({ id: "raw-http-proxy", instantiate: () => createProxy(), + causesSideEffects: true, }); export default rawHttpProxyInjectable; diff --git a/packages/core/src/main/router/route-request.injectable.ts b/packages/core/src/main/router/route-request.injectable.ts index b75abc1ede..d0bb7e1d25 100644 --- a/packages/core/src/main/router/route-request.injectable.ts +++ b/packages/core/src/main/router/route-request.injectable.ts @@ -10,8 +10,8 @@ import Call from "@hapi/call"; import Subtext from "@hapi/subtext"; import type http from "http"; import type { Cluster } from "../../common/cluster/cluster"; -import type { ServerIncomingMessage } from "../lens-proxy/lens-proxy"; import type { RouteHandler } from "./create-handler-for-route.injectable"; +import type { ProxyIncomingMessage } from "../lens-proxy/messages"; export const routeInjectionToken = getInjectionToken>({ id: "route-injection-token", @@ -26,7 +26,7 @@ export function getRouteInjectable( }); } -export type RouteRequest = (cluster: Cluster | undefined, req: ServerIncomingMessage, res: http.ServerResponse) => Promise; +export type RouteRequest = (cluster: Cluster | undefined, req: ProxyIncomingMessage, res: http.ServerResponse) => Promise; const createRouter = (di: DiContainerForInjection) => { const routes = di.injectMany(routeInjectionToken); diff --git a/packages/core/src/main/routes/files/static-file-route.injectable.ts b/packages/core/src/main/routes/files/static-file-route.injectable.ts index 0268ac2051..ec46b19d59 100644 --- a/packages/core/src/main/routes/files/static-file-route.injectable.ts +++ b/packages/core/src/main/routes/files/static-file-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import isDevelopmentInjectable from "../../../common/vars/is-development.injectable"; import { route } from "../../router/route"; import prodStaticFileRouteHandlerInjectable from "./production.injectable"; diff --git a/packages/core/src/main/routes/helm/charts/get-readme-route.injectable.ts b/packages/core/src/main/routes/helm/charts/get-readme-route.injectable.ts index f3b52073c2..c72fdd7193 100644 --- a/packages/core/src/main/routes/helm/charts/get-readme-route.injectable.ts +++ b/packages/core/src/main/routes/helm/charts/get-readme-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { apiPrefix } from "../../../../common/vars"; import { route } from "../../../router/route"; import getHelmChartReadmeInjectable from "../../../helm/helm-service/get-helm-chart-readme.injectable"; diff --git a/packages/core/src/main/routes/helm/charts/get-values-route.injectable.ts b/packages/core/src/main/routes/helm/charts/get-values-route.injectable.ts index 49efe5fb0c..b997766c7b 100644 --- a/packages/core/src/main/routes/helm/charts/get-values-route.injectable.ts +++ b/packages/core/src/main/routes/helm/charts/get-values-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { apiPrefix } from "../../../../common/vars"; import { route } from "../../../router/route"; import getHelmChartValuesInjectable from "../../../helm/helm-service/get-helm-chart-values.injectable"; diff --git a/packages/core/src/main/routes/helm/charts/get-versions-route.injectable.ts b/packages/core/src/main/routes/helm/charts/get-versions-route.injectable.ts index 933d94743b..a0689f2c22 100644 --- a/packages/core/src/main/routes/helm/charts/get-versions-route.injectable.ts +++ b/packages/core/src/main/routes/helm/charts/get-versions-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { apiPrefix } from "../../../../common/vars"; import { route } from "../../../router/route"; import getHelmChartVersionsInjectable from "../../../helm/helm-service/get-helm-chart-versions.injectable"; diff --git a/packages/core/src/main/routes/helm/charts/list-route.injectable.ts b/packages/core/src/main/routes/helm/charts/list-route.injectable.ts index 402a3d7cd1..7dbcc1f522 100644 --- a/packages/core/src/main/routes/helm/charts/list-route.injectable.ts +++ b/packages/core/src/main/routes/helm/charts/list-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { apiPrefix } from "../../../../common/vars"; import { route } from "../../../router/route"; import listHelmChartsInjectable from "../../../helm/helm-service/list-helm-charts.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/delete-release-route.injectable.ts b/packages/core/src/main/routes/helm/releases/delete-release-route.injectable.ts index 79d3195643..4b1fa92a6e 100644 --- a/packages/core/src/main/routes/helm/releases/delete-release-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/delete-release-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { clusterRoute } from "../../../router/route"; import deleteClusterHelmReleaseInjectable from "../../../helm/helm-service/delete-helm-release.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/get-release-history-route.injectable.ts b/packages/core/src/main/routes/helm/releases/get-release-history-route.injectable.ts index 2ba1349de0..db2892b978 100644 --- a/packages/core/src/main/routes/helm/releases/get-release-history-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/get-release-history-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { clusterRoute } from "../../../router/route"; import getClusterHelmReleaseHistoryInjectable from "../../../helm/helm-service/get-helm-release-history.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/get-release-route.injectable.ts b/packages/core/src/main/routes/helm/releases/get-release-route.injectable.ts index 7b264b4fe9..4c6b289ec0 100644 --- a/packages/core/src/main/routes/helm/releases/get-release-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/get-release-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { clusterRoute } from "../../../router/route"; import getHelmReleaseInjectable from "../../../helm/helm-service/get-helm-release.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/get-release-values-route.injectable.ts b/packages/core/src/main/routes/helm/releases/get-release-values-route.injectable.ts index 78799f3e58..21e30a4c98 100644 --- a/packages/core/src/main/routes/helm/releases/get-release-values-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/get-release-values-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { getBoolean } from "../../../utils/parse-query"; import { contentTypes } from "../../../router/router-content-types"; import { clusterRoute } from "../../../router/route"; diff --git a/packages/core/src/main/routes/helm/releases/install-chart-route.injectable.ts b/packages/core/src/main/routes/helm/releases/install-chart-route.injectable.ts index e34d54db23..d6d8619b50 100644 --- a/packages/core/src/main/routes/helm/releases/install-chart-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/install-chart-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import Joi from "joi"; import { payloadValidatedClusterRoute } from "../../../router/route"; import type { InstallChartArgs } from "../../../helm/helm-service/install-helm-chart.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/list-releases-route.injectable.ts b/packages/core/src/main/routes/helm/releases/list-releases-route.injectable.ts index 53a4dcb179..4798956cfd 100644 --- a/packages/core/src/main/routes/helm/releases/list-releases-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/list-releases-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { clusterRoute } from "../../../router/route"; import listClusterHelmReleasesInjectable from "../../../helm/helm-service/list-helm-releases.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/rollback-release-route.injectable.ts b/packages/core/src/main/routes/helm/releases/rollback-release-route.injectable.ts index 49a8fddb88..e08d835620 100644 --- a/packages/core/src/main/routes/helm/releases/rollback-release-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/rollback-release-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import Joi from "joi"; import { payloadValidatedClusterRoute } from "../../../router/route"; import rollbackClusterHelmReleaseInjectable from "../../../helm/helm-service/rollback-helm-release.injectable"; diff --git a/packages/core/src/main/routes/helm/releases/update-release-route.injectable.ts b/packages/core/src/main/routes/helm/releases/update-release-route.injectable.ts index 5993d7922d..1b062cf439 100644 --- a/packages/core/src/main/routes/helm/releases/update-release-route.injectable.ts +++ b/packages/core/src/main/routes/helm/releases/update-release-route.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { apiPrefix } from "../../../../common/vars"; -import { getRouteInjectable } from "../../../router/router.injectable"; +import { getRouteInjectable } from "../../../router/route-request.injectable"; import { payloadValidatedClusterRoute } from "../../../router/route"; import Joi from "joi"; import type { UpdateChartArgs } from "../../../helm/helm-service/update-helm-release.injectable"; diff --git a/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts b/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts index b6b77d5a40..6fb2b344fe 100644 --- a/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts +++ b/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts @@ -4,7 +4,7 @@ */ import { apiPrefix } from "../../../common/vars"; -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import type { V1Secret } from "@kubernetes/client-node"; import { CoreV1Api } from "@kubernetes/client-node"; diff --git a/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts b/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts index fe3d2b01fa..a718d9ba97 100644 --- a/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts +++ b/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts @@ -4,7 +4,7 @@ */ import { apiPrefix } from "../../../common/vars"; -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import type { ClusterPrometheusMetadata } from "../../../common/cluster-types"; import { ClusterMetadataKey } from "../../../common/cluster-types"; import type { Cluster } from "../../../common/cluster/cluster"; diff --git a/packages/core/src/main/routes/metrics/get-metric-providers-route.injectable.ts b/packages/core/src/main/routes/metrics/get-metric-providers-route.injectable.ts index 54dfd9bb95..909b368411 100644 --- a/packages/core/src/main/routes/metrics/get-metric-providers-route.injectable.ts +++ b/packages/core/src/main/routes/metrics/get-metric-providers-route.injectable.ts @@ -4,7 +4,7 @@ */ import { apiPrefix } from "../../../common/vars"; -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { route } from "../../router/route"; import prometheusProvidersInjectable from "../../prometheus/providers.injectable"; diff --git a/packages/core/src/main/routes/port-forward/get-current-port-forward-route.injectable.ts b/packages/core/src/main/routes/port-forward/get-current-port-forward-route.injectable.ts index 769046c804..46c2db3f11 100644 --- a/packages/core/src/main/routes/port-forward/get-current-port-forward-route.injectable.ts +++ b/packages/core/src/main/routes/port-forward/get-current-port-forward-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { apiPrefix } from "../../../common/vars"; import { PortForward } from "./functionality/port-forward"; import { clusterRoute } from "../../router/route"; diff --git a/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts b/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts index 170f93fef8..0aa2a7987a 100644 --- a/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts +++ b/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { apiPrefix } from "../../../common/vars"; import { PortForward } from "./functionality/port-forward"; import createPortForwardInjectable from "./functionality/create-port-forward.injectable"; diff --git a/packages/core/src/main/routes/port-forward/stop-current-port-forward-route.injectable.ts b/packages/core/src/main/routes/port-forward/stop-current-port-forward-route.injectable.ts index 1fc76e9b72..98dab3b995 100644 --- a/packages/core/src/main/routes/port-forward/stop-current-port-forward-route.injectable.ts +++ b/packages/core/src/main/routes/port-forward/stop-current-port-forward-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { apiPrefix } from "../../../common/vars"; import { PortForward } from "./functionality/port-forward"; import { clusterRoute } from "../../router/route"; diff --git a/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts b/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts index a2d8766170..59b5123973 100644 --- a/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts +++ b/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { apiPrefix } from "../../../common/vars"; import { payloadValidatedClusterRoute } from "../../router/route"; import Joi from "joi"; diff --git a/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts b/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts index 6cac0436f5..fae062f069 100644 --- a/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts +++ b/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { apiPrefix } from "../../../common/vars"; import { payloadValidatedClusterRoute } from "../../router/route"; import Joi from "joi"; diff --git a/packages/core/src/main/routes/versions/get-version-route.injectable.ts b/packages/core/src/main/routes/versions/get-version-route.injectable.ts index d132e242d6..c3a8f9304a 100644 --- a/packages/core/src/main/routes/versions/get-version-route.injectable.ts +++ b/packages/core/src/main/routes/versions/get-version-route.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRouteInjectable } from "../../router/router.injectable"; +import { getRouteInjectable } from "../../router/route-request.injectable"; import { route } from "../../router/route"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; diff --git a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts index 7c25332c70..e240388fd8 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts @@ -49,6 +49,7 @@ const setupLensProxyInjectable = getInjectable({ logger.info("⚡ LensProxy connection OK"); } catch (error) { + console.log(error); logger.error(`🛑 LensProxy: failed connection test: ${error}`); const hostsPath = isWindows @@ -69,8 +70,6 @@ const setupLensProxyInjectable = getInjectable({ runAfter: initializeBuildVersionInjectable, }), - causesSideEffects: true, - injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx index 731c5ba8c7..92a0605996 100644 --- a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx +++ b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx @@ -32,7 +32,6 @@ import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTest import assert from "assert"; import { openMenu } from "react-select-event"; import userEvent from "@testing-library/user-event"; -import lensProxyPortInjectable from "../../../main/lens-proxy/lens-proxy-port.injectable"; import type { Route } from "../../../common/front-end-routing/front-end-route-injection-token"; import type { NavigateToRouteOptions } from "../../../common/front-end-routing/navigate-to-route-injection-token"; import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token"; @@ -72,6 +71,7 @@ import { applicationFeature, startApplicationInjectionToken } from "@k8slens/app import { testUsingFakeTime } from "../../../test-utils/use-fake-time"; import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import { getMessageBridgeFake } from "@k8slens/messaging-fake-bridge"; +import { overrideFetchingInternalRoutes } from "../../../test-utils/override-internal-backend-routes.injectable"; type MainDiCallback = (container: { mainDi: DiContainer }) => void | Promise; type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise; @@ -192,6 +192,7 @@ export const getApplicationBuilder = () => { const overrideFsWithFakes = getOverrideFsWithFakes(); overrideFsWithFakes(mainDi); + overrideFetchingInternalRoutes(mainDi); // Set up ~/.kube as existing as a folder { @@ -235,6 +236,7 @@ export const getApplicationBuilder = () => { messageBridgeFake.involve(windowDi); overrideFsWithFakes(windowDi); + overrideFetchingInternalRoutes(mainDi, windowDi); runInAction(() => { registerFeature( @@ -310,8 +312,6 @@ export const getApplicationBuilder = () => { const startApplication = mainDi.inject(startApplicationInjectionToken); const startApp = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => { - mainDi.inject(lensProxyPortInjectable).set(42); - for (const callback of beforeApplicationStartCallbacks) { await callback({ mainDi }); } diff --git a/packages/core/src/test-utils/override-internal-backend-routes.injectable.ts b/packages/core/src/test-utils/override-internal-backend-routes.injectable.ts new file mode 100644 index 0000000000..3ce83ddcdc --- /dev/null +++ b/packages/core/src/test-utils/override-internal-backend-routes.injectable.ts @@ -0,0 +1,85 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { DiContainer } from "@ogre-tools/injectable"; +import lensFetchInjectable from "../common/fetch/lens-fetch.injectable"; +import { Headers, Response } from "@k8slens/node-fetch"; +import handleRouteRequestInjectable from "../main/lens-proxy/handle-route-request.injectable"; +import fetchInjectable from "../common/fetch/fetch.injectable"; +import * as Shot from "@hapi/shot"; + +export const overrideFetchingInternalRoutes = (mainDi: DiContainer, targetDi = mainDi) => { + targetDi.override(lensFetchInjectable, () => async (pathname, init = {}) => { + // NOTE: This injects things from the other environment on purpose + const handleRouteRequest = mainDi.inject(handleRouteRequestInjectable); + + const response = await Shot.inject( + handleRouteRequest as Shot.MaybeInjectionListener, + { + url: pathname, + headers: new Headers(init?.headers).raw(), + method: init?.method, + payload: init?.body ?? undefined, + }, + ); + + return new Response(response.rawPayload, { + headers: Object.entries(response.headers).map(([key, value]) => { + if (value === undefined) { + return [key]; + } else if (Array.isArray(value)) { + return [key, value.join(",")]; + } else { + return [key, value.toString()]; + } + }), + status: response.statusCode, + statusText: response.statusMessage, + }); + }); + + targetDi.override(fetchInjectable, () => async (rawUrl, init = {}) => { + // NOTE: This injects things from the other environment on purpose + const handleRouteRequest = mainDi.inject(handleRouteRequestInjectable); + const url = new URL(rawUrl); + + switch (url.host) { + case "localhost": + case "127.0.0.1": + case "lens.app": + break; + default: + if (url.host.endsWith(".lens.app")) { + break; + } + + throw new Error("Tried to fetch an external resource"); + } + + const response = await Shot.inject( + handleRouteRequest as Shot.MaybeInjectionListener, + { + url: url.pathname, + headers: new Headers(init?.headers).raw(), + method: init?.method, + payload: init?.body ?? undefined, + }, + ); + + return new Response(response.rawPayload, { + headers: Object.entries(response.headers).map(([key, value]) => { + if (value === undefined) { + return [key]; + } else if (Array.isArray(value)) { + return [key, value.join(",")]; + } else { + return [key, value.toString()]; + } + }), + status: response.statusCode, + statusText: response.statusMessage, + }); + }); +};