mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make shell sessions even more injectable
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
28227c923d
commit
a733641f62
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { computed } from "mobx";
|
||||
import userStoreInjectable from "./user-store.injectable";
|
||||
|
||||
const downloadKubectlBinariesInjectable = getInjectable({
|
||||
id: "download-kubectl-binaries",
|
||||
instantiate: (di) => {
|
||||
const store = di.inject(userStoreInjectable);
|
||||
|
||||
return computed(() => store.downloadKubectlBinaries);
|
||||
},
|
||||
});
|
||||
|
||||
export default downloadKubectlBinariesInjectable;
|
||||
18
src/common/user-store/kubectl-binaries-path.injectable.ts
Normal file
18
src/common/user-store/kubectl-binaries-path.injectable.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { computed } from "mobx";
|
||||
import userStoreInjectable from "./user-store.injectable";
|
||||
|
||||
const kubectlBinariesPathInjectable = getInjectable({
|
||||
id: "kubectl-binaries-path",
|
||||
instantiate: (di) => {
|
||||
const store = di.inject(userStoreInjectable);
|
||||
|
||||
return computed(() => store.kubectlBinariesPath);
|
||||
},
|
||||
});
|
||||
|
||||
export default kubectlBinariesPathInjectable;
|
||||
@ -7,14 +7,14 @@ import { clearKubeconfigEnvVars } from "../utils/clear-kube-env-vars";
|
||||
|
||||
describe("clearKubeconfigEnvVars tests", () => {
|
||||
it("should not touch non kubeconfig keys", () => {
|
||||
expect(clearKubeconfigEnvVars({ a: 1 })).toStrictEqual({ a: 1 });
|
||||
expect(clearKubeconfigEnvVars({ a: "1" })).toStrictEqual({ a: 1 });
|
||||
});
|
||||
|
||||
it("should remove a single kubeconfig key", () => {
|
||||
expect(clearKubeconfigEnvVars({ a: 1, kubeconfig: "1" })).toStrictEqual({ a: 1 });
|
||||
expect(clearKubeconfigEnvVars({ a: "1", kubeconfig: "1" })).toStrictEqual({ a: 1 });
|
||||
});
|
||||
|
||||
it("should remove a two kubeconfig key", () => {
|
||||
expect(clearKubeconfigEnvVars({ a: 1, kubeconfig: "1", kUbeconfig: "1" })).toStrictEqual({ a: 1 });
|
||||
expect(clearKubeconfigEnvVars({ a: "1", kubeconfig: "1", kUbeconfig: "1" })).toStrictEqual({ a: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { IComputedValue } from "mobx";
|
||||
import path from "path";
|
||||
import { UserStore } from "../../../common/user-store";
|
||||
import type { TerminalShellEnvModify } from "../shell-env-modifier/terminal-shell-env-modify.injectable";
|
||||
import type { ShellSessionArgs, ShellSessionDependencies } from "../shell-session";
|
||||
import { ShellSession } from "../shell-session";
|
||||
@ -12,6 +12,8 @@ import { ShellSession } from "../shell-session";
|
||||
export interface LocalShellSessionDependencies extends ShellSessionDependencies {
|
||||
terminalShellEnvModify: TerminalShellEnvModify;
|
||||
readonly baseBundeledBinariesDirectory: string;
|
||||
readonly kubectlBinariesPath: IComputedValue<string | undefined>;
|
||||
readonly downloadKubectlBinaries: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
export class LocalShellSession extends ShellSession {
|
||||
@ -30,11 +32,8 @@ export class LocalShellSession extends ShellSession {
|
||||
}
|
||||
|
||||
public async open() {
|
||||
let env = await this.getCachedShellEnv();
|
||||
|
||||
// extensions can modify the env
|
||||
env = this.dependencies.terminalShellEnvModify(this.cluster.id, env);
|
||||
|
||||
const cachedEnv = await this.getCachedShellEnv();
|
||||
const env = this.dependencies.terminalShellEnvModify(this.cluster.id, cachedEnv);
|
||||
const shell = env.PTYSHELL;
|
||||
|
||||
if (!shell) {
|
||||
@ -47,8 +46,8 @@ export class LocalShellSession extends ShellSession {
|
||||
}
|
||||
|
||||
protected async getShellArgs(shell: string): Promise<string[]> {
|
||||
const pathFromPreferences = UserStore.getInstance().kubectlBinariesPath || this.kubectl.getBundledPath();
|
||||
const kubectlPathDir = UserStore.getInstance().downloadKubectlBinaries ? await this.kubectlBinDirP : path.dirname(pathFromPreferences);
|
||||
const pathFromPreferences = this.dependencies.kubectlBinariesPath.get() || this.kubectl.getBundledPath();
|
||||
const kubectlPathDir = this.dependencies.downloadKubectlBinaries.get() ? await this.kubectlBinDirP : path.dirname(pathFromPreferences);
|
||||
|
||||
switch(path.basename(shell)) {
|
||||
case "powershell.exe":
|
||||
|
||||
@ -10,6 +10,12 @@ import type WebSocket from "ws";
|
||||
import terminalShellEnvModifyInjectable from "../shell-env-modifier/terminal-shell-env-modify.injectable";
|
||||
import baseBundeledBinariesDirectoryInjectable from "../../../common/vars/base-bundled-binaries-dir.injectable";
|
||||
import type { Kubectl } from "../../kubectl/kubectl";
|
||||
import kubectlBinariesPathInjectable from "../../../common/user-store/kubectl-binaries-path.injectable";
|
||||
import downloadKubectlBinariesInjectable from "../../../common/user-store/download-kubectl-binaries.injectable";
|
||||
import ensureShellProcessInjectable from "../ensure-shell-process.injectable";
|
||||
import getCachedShellEnvInjectable from "../get-cached-shell-env.injectable";
|
||||
import getValidCwdInjectable from "../get-valid-cwd.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface OpenLocalShellSessionArgs {
|
||||
websocket: WebSocket;
|
||||
@ -26,6 +32,12 @@ const openLocalShellSessionInjectable = getInjectable({
|
||||
const deps: LocalShellSessionDependencies = {
|
||||
terminalShellEnvModify: di.inject(terminalShellEnvModifyInjectable),
|
||||
baseBundeledBinariesDirectory: di.inject(baseBundeledBinariesDirectoryInjectable),
|
||||
kubectlBinariesPath: di.inject(kubectlBinariesPathInjectable),
|
||||
downloadKubectlBinaries: di.inject(downloadKubectlBinariesInjectable),
|
||||
ensureShellProcess: di.inject(ensureShellProcessInjectable),
|
||||
getCachedShellEnv: di.inject(getCachedShellEnvInjectable),
|
||||
getValidCwd: di.inject(getValidCwdInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
};
|
||||
|
||||
return (args) => new LocalShellSession(deps, args).open();
|
||||
|
||||
@ -5,8 +5,13 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { Cluster } from "../../../common/cluster/cluster";
|
||||
import type WebSocket from "ws";
|
||||
import type { NodeShellSessionDependencies } from "./node-shell-session";
|
||||
import { NodeShellSession } from "./node-shell-session";
|
||||
import type { Kubectl } from "../../kubectl/kubectl";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import ensureShellProcessInjectable from "../ensure-shell-process.injectable";
|
||||
import getCachedShellEnvInjectable from "../get-cached-shell-env.injectable";
|
||||
import getValidCwdInjectable from "../get-valid-cwd.injectable";
|
||||
|
||||
export interface OpenNodeShellSessionArgs {
|
||||
websocket: WebSocket;
|
||||
@ -21,7 +26,16 @@ export type OpenNodeShellSession = (args: OpenNodeShellSessionArgs) => Promise<v
|
||||
const openNodeShellSessionInjectable = getInjectable({
|
||||
id: "node-shell-session",
|
||||
|
||||
instantiate: (): OpenNodeShellSession => (args) => new NodeShellSession(args).open(),
|
||||
instantiate: (di): OpenNodeShellSession => {
|
||||
const dependencies: NodeShellSessionDependencies = {
|
||||
ensureShellProcess: di.inject(ensureShellProcessInjectable),
|
||||
getCachedShellEnv: di.inject(getCachedShellEnvInjectable),
|
||||
getValidCwd: di.inject(getValidCwdInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
};
|
||||
|
||||
return (args) => new NodeShellSession(dependencies, args).open();
|
||||
},
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
|
||||
@ -5,9 +5,11 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { spawn } from "node-pty";
|
||||
|
||||
export type SpawnPty = typeof spawn;
|
||||
|
||||
const spawnPtyInjectable = getInjectable({
|
||||
id: "spawn-pty",
|
||||
instantiate: () => spawn,
|
||||
instantiate: (): SpawnPty => spawn,
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import terminalConfigInjectable from "../../../../common/user-store/terminal-con
|
||||
import terminalCopyOnSelectInjectable from "../../../../common/user-store/terminal-copy-on-select.injectable";
|
||||
import themeStoreInjectable from "../../../themes/store.injectable";
|
||||
import allowTerminalTransparencyInjectable from "./allow-transparency.injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
|
||||
export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal;
|
||||
|
||||
@ -24,6 +25,7 @@ const createTerminalInjectable = getInjectable({
|
||||
terminalCopyOnSelect: di.inject(terminalCopyOnSelectInjectable),
|
||||
themeStore: di.inject(themeStoreInjectable),
|
||||
allowTransparency: di.inject(allowTerminalTransparencyInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
};
|
||||
|
||||
return (tabId, api) => new Terminal(dependencies, { tabId, api });
|
||||
|
||||
@ -15,7 +15,7 @@ import { disposer } from "../../../utils";
|
||||
import { isMac } from "../../../../common/vars";
|
||||
import { once } from "lodash";
|
||||
import { clipboard } from "electron";
|
||||
import logger from "../../../../common/logger";
|
||||
import type { Logger } from "../../../../common/logger";
|
||||
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
|
||||
import assert from "assert";
|
||||
import { TerminalChannels } from "../../../../common/terminal/channels";
|
||||
@ -26,6 +26,7 @@ export interface TerminalDependencies {
|
||||
readonly terminalCopyOnSelect: IComputedValue<boolean>;
|
||||
readonly themeStore: ThemeStore;
|
||||
readonly allowTransparency: boolean;
|
||||
readonly logger: Logger;
|
||||
}
|
||||
|
||||
export interface TerminalArguments {
|
||||
@ -196,14 +197,14 @@ export class Terminal {
|
||||
};
|
||||
|
||||
setFontSize = (fontSize: number) => {
|
||||
logger.info(`[TERMINAL]: set fontSize to ${fontSize}`);
|
||||
this.dependencies.logger.info(`[TERMINAL]: set fontSize to ${fontSize}`);
|
||||
|
||||
this.xterm.options.fontSize = fontSize;
|
||||
this.fit();
|
||||
};
|
||||
|
||||
setFontFamily = (fontFamily: string) => {
|
||||
logger.info(`[TERMINAL]: set fontFamily to ${fontFamily}`);
|
||||
this.dependencies.logger.info(`[TERMINAL]: set fontFamily to ${fontFamily}`);
|
||||
|
||||
this.xterm.options.fontFamily = fontFamily;
|
||||
this.fit();
|
||||
|
||||
@ -4,18 +4,44 @@
|
||||
*/
|
||||
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { waitFor } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import getShellAuthTokenChannelHandlerInjectable from "../../main/lens-proxy/proxy-functions/shell/auth-token-channel-handler.injectable";
|
||||
import type { GetShellAuthToken } from "../../common/shell-authentication/get-auth-token.injectable";
|
||||
import type { SpawnPty } from "../../main/shell-session/spawn-pty.injectable";
|
||||
import spawnPtyInjectable from "../../main/shell-session/spawn-pty.injectable";
|
||||
import type { IPty } from "node-pty";
|
||||
|
||||
describe("local shell session techincal tests", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let result: RenderResult;
|
||||
let authenticationSpy: jest.SpyInstance<Uint8Array | Promise<Uint8Array>, Parameters<GetShellAuthToken>>;
|
||||
let spawnPtyMock: jest.MockedFunction<SpawnPty>;
|
||||
let ptyMock: jest.MockedObject<IPty>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder()
|
||||
.beforeApplicationStart(() => {
|
||||
spawnPtyMock = jest.fn();
|
||||
builder.dis.mainDi.override(spawnPtyInjectable, () => spawnPtyMock);
|
||||
|
||||
spawnPtyMock.mockImplementation(() => ptyMock = {
|
||||
cols: 80,
|
||||
rows: 40,
|
||||
pid: 12346,
|
||||
process: "my-mocked-shell",
|
||||
handleFlowControl: true,
|
||||
kill: jest.fn(),
|
||||
onData: jest.fn(),
|
||||
onExit: jest.fn(),
|
||||
on: jest.fn(),
|
||||
resize: jest.fn(),
|
||||
write: jest.fn(),
|
||||
pause: jest.fn(),
|
||||
resume: jest.fn(),
|
||||
});
|
||||
})
|
||||
.beforeRender(() => {
|
||||
const shellAuthentication = builder.dis.mainDi.inject(getShellAuthTokenChannelHandlerInjectable);
|
||||
|
||||
@ -34,4 +60,9 @@ describe("local shell session techincal tests", () => {
|
||||
it("should call the authentication function", () => {
|
||||
expect(authenticationSpy).toBeCalled();
|
||||
});
|
||||
|
||||
it("should create a pty instance", async () => {
|
||||
await waitFor(() => expect(spawnPtyMock).toBeCalled());
|
||||
void ptyMock;
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user