Replace kubectl-proxy with lens-k8s-proxy (#4924)

This commit is contained in:
Jari Kolehmainen authored and GitHub committed 2022-02-28 09:37:29 -05:00
1 parent f5a7d64551
commit c04a3b8d33
10 files changed
+191 -31

No files matched your search

@@ -0,0 +1,22 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import path from "path";
import isDevelopmentInjectable from "../../vars/is-development.injectable";
import contextDirInjectable from "../../vars/context-dir.injectable";
const directoryForBundledBinariesInjectable = getInjectable({
id: "directory-for-bundled-binaries",
instantiate: (di) => {
if (di.inject(isDevelopmentInjectable)) {
return path.join(di.inject(contextDirInjectable), "binaries");
}
return process.resourcesPath;
},
lifecycle: lifecycleEnum.singleton,
});
export default directoryForBundledBinariesInjectable;
+14
View File
@@ -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, lifecycleEnum } from "@ogre-tools/injectable";
import { contextDir } from "../vars";
const contextDirInjectable = getInjectable({
id: "context-dir",
instantiate: () => contextDir,
lifecycle: lifecycleEnum.singleton,
});
export default contextDirInjectable;
@@ -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, lifecycleEnum } from "@ogre-tools/injectable";
import { isDevelopment } from "../vars";
const isDevelopmentInjectable = getInjectable({
id: "is-development",
instantiate: () => isDevelopment,
lifecycle: lifecycleEnum.singleton,
});
export default isDevelopmentInjectable;
+3 -2
View File
@@ -38,7 +38,7 @@ import type { Cluster } from "../../common/cluster/cluster";
import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
import { broadcastMessage } from "../../common/ipc";
import { ChildProcess, spawn } from "child_process";
import { bundledKubectlPath, Kubectl } from "../kubectl/kubectl";
import { Kubectl } from "../kubectl/kubectl";
import { mock, MockProxy } from "jest-mock-extended";
import { waitUntilUsed } from "tcp-port-used";
import { EventEmitter, Readable } from "stream";
@@ -49,6 +49,7 @@ import mockFs from "mock-fs";
import { getDiForUnitTesting } from "../getDiForUnitTesting";
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
import path from "path";
console = new Console(stdout, stderr);
@@ -194,7 +195,7 @@ describe("kube auth proxy tests", () => {
return mockedCP.stdout;
});
mockSpawn.mockImplementationOnce((command: string): ChildProcess => {
expect(command).toBe(bundledKubectlPath());
expect(path.basename(command).split(".")[0]).toBe("lens-k8s-proxy");
return mockedCP;
});
+1 -1
View File
@@ -118,7 +118,7 @@ export class ContextHandler {
await this.ensureServer();
const path = this.clusterUrl.path !== "/" ? this.clusterUrl.path : "";
return `http://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix}${path}`;
return `http://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix.slice(0, -1)}${path}`;
}
async getApiTarget(isLongRunningRequest = false): Promise<httpProxy.ServerOptions> {
+2
View File
@@ -14,6 +14,7 @@ import appNameInjectable from "./app-paths/app-name/app-name.injectable";
import registerChannelInjectable from "./app-paths/register-channel/register-channel.injectable";
import writeJsonFileInjectable from "../common/fs/write-json-file.injectable";
import readJsonFileInjectable from "../common/fs/read-json-file.injectable";
import directoryForBundledBinariesInjectable from "../common/app-paths/directory-for-bundled-binaries/directory-for-bundled-binaries.injectable";
export const getDiForUnitTesting = (
{ doGeneralOverrides } = { doGeneralOverrides: false },
@@ -43,6 +44,7 @@ export const getDiForUnitTesting = (
di.override(setElectronAppPathInjectable, () => () => undefined);
di.override(appNameInjectable, () => "some-electron-app-name");
di.override(registerChannelInjectable, () => () => undefined);
di.override(directoryForBundledBinariesInjectable, () => "some-bin-directory");
di.override(writeJsonFileInjectable, () => () => {
throw new Error("Tried to write JSON file to file system without specifying explicit override.");
@@ -5,16 +5,18 @@
import { getInjectable } from "@ogre-tools/injectable";
import { KubeAuthProxy } from "./kube-auth-proxy";
import type { Cluster } from "../../common/cluster/cluster";
import bundledKubectlInjectable from "../kubectl/bundled-kubectl.injectable";
import path from "path";
import { isDevelopment, isWindows } from "../../common/vars";
import directoryForBundledBinariesInjectable from "../../common/app-paths/directory-for-bundled-binaries/directory-for-bundled-binaries.injectable";
const createKubeAuthProxyInjectable = getInjectable({
id: "create-kube-auth-proxy",
instantiate: (di) => {
const bundledKubectl = di.inject(bundledKubectlInjectable);
const binaryName = isWindows ? "lens-k8s-proxy.exe" : "lens-k8s-proxy";
const proxyPath = isDevelopment ? path.join("client", process.platform, process.arch) : process.arch;
const dependencies = {
getProxyBinPath: bundledKubectl.getPath,
proxyBinPath: path.join(di.inject(directoryForBundledBinariesInjectable), proxyPath, binaryName),
};
return (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) =>
+13 -24
View File
@@ -8,18 +8,17 @@ import { waitUntilUsed } from "tcp-port-used";
import { randomBytes } from "crypto";
import type { Cluster } from "../../common/cluster/cluster";
import logger from "../logger";
import * as url from "url";
import { getPortFrom } from "../utils/get-port";
import { makeObservable, observable, when } from "mobx";
const startingServeRegex = /^starting to serve on (?<address>.+)/i;
const startingServeRegex = /starting to serve on (?<address>.+)/i;
interface Dependencies {
getProxyBinPath: () => Promise<string>;
proxyBinPath: string;
}
export class KubeAuthProxy {
public readonly apiPrefix = `/${randomBytes(8).toString("hex")}`;
public readonly apiPrefix = `/${randomBytes(8).toString("hex")}/`;
public get port(): number {
return this._port;
@@ -27,13 +26,10 @@ export class KubeAuthProxy {
protected _port: number;
protected proxyProcess?: ChildProcess;
protected readonly acceptHosts: string;
@observable protected ready = false;
constructor(private dependencies: Dependencies, protected readonly cluster: Cluster, protected readonly env: NodeJS.ProcessEnv) {
makeObservable(this);
this.acceptHosts = url.parse(this.cluster.apiUrl).hostname;
}
get whenReady() {
@@ -45,23 +41,16 @@ export class KubeAuthProxy {
return this.whenReady;
}
const proxyBin = await this.dependencies.getProxyBinPath();
const args = [
"proxy",
"-p", "0",
"--kubeconfig", `${this.cluster.kubeConfigPath}`,
"--context", `${this.cluster.contextName}`,
"--accept-hosts", this.acceptHosts,
"--reject-paths", "^[^/]",
"--api-prefix", this.apiPrefix,
];
if (process.env.DEBUG_PROXY === "true") {
args.push("-v", "9");
}
logger.debug(`spawning kubectl proxy with args: ${args}`);
this.proxyProcess = spawn(proxyBin, args, { env: this.env });
const proxyBin = this.dependencies.proxyBinPath;
this.proxyProcess = spawn(proxyBin, [], {
env: {
...this.env,
KUBECONFIG: this.cluster.kubeConfigPath,
KUBECONFIG_CONTEXT: this.cluster.contextName,
API_PREFIX: this.apiPrefix,
},
});
this.proxyProcess.on("error", (error) => {
this.cluster.broadcastConnectUpdate(error.message, true);
this.exit();