mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make ResourceStack fully injectable (#6591)
Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
055a13d4a9
commit
6142aad5ab
15 files changed
+343
-140
No files matched your search
-3
@@ -12,7 +12,6 @@ import catalogEntityRegistryInjectable from "../../../catalog/entity-registry.in
|
||||
import askUserForFilePathsInjectable from "../../../ipc/ask-user-for-file-paths.injectable";
|
||||
import applicationMenuItemCompositeInjectable from "../../../../features/application-menu/main/application-menu-item-composite.injectable";
|
||||
import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable";
|
||||
import createResourceApplierInjectable from "../../../resource-applier/create-resource-applier.injectable";
|
||||
|
||||
const setupIpcMainHandlersInjectable = getInjectable({
|
||||
id: "setup-ipc-main-handlers",
|
||||
@@ -25,7 +24,6 @@ const setupIpcMainHandlersInjectable = getInjectable({
|
||||
const operatingSystemTheme = di.inject(operatingSystemThemeInjectable);
|
||||
const askUserForFilePaths = di.inject(askUserForFilePathsInjectable);
|
||||
const emitAppEvent = di.inject(emitAppEventInjectable);
|
||||
const createResourceApplier = di.inject(createResourceApplierInjectable);
|
||||
|
||||
return {
|
||||
id: "setup-ipc-main-handlers",
|
||||
@@ -39,7 +37,6 @@ const setupIpcMainHandlersInjectable = getInjectable({
|
||||
operatingSystemTheme,
|
||||
askUserForFilePaths,
|
||||
emitAppEvent,
|
||||
createResourceApplier,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import type { IpcMainInvokeEvent } from "electron";
|
||||
import { BrowserWindow, Menu } from "electron";
|
||||
import { clusterFrameMap } from "../../../../common/cluster-frames";
|
||||
import { clusterActivateHandler, clusterSetFrameIdHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler } from "../../../../common/ipc/cluster";
|
||||
import { clusterActivateHandler, clusterSetFrameIdHandler, clusterDisconnectHandler } from "../../../../common/ipc/cluster";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import { ClusterStore } from "../../../../common/cluster-store/cluster-store";
|
||||
import { broadcastMainChannel, broadcastMessage, ipcMainHandle, ipcMainOn } from "../../../../common/ipc";
|
||||
@@ -23,7 +23,6 @@ import type { Composite } from "../../../../common/utils/composite/get-composite
|
||||
import { getApplicationMenuTemplate } from "../../../../features/application-menu/main/populate-application-menu.injectable";
|
||||
import type { MenuItemRoot } from "../../../../features/application-menu/main/application-menu-item-composite.injectable";
|
||||
import type { EmitAppEvent } from "../../../../common/app-event-bus/emit-event.injectable";
|
||||
import type { CreateResourceApplier } from "../../../resource-applier/create-resource-applier.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
applicationMenuItemComposite: IComputedValue<Composite<ApplicationMenuItemTypes | MenuItemRoot>>;
|
||||
@@ -32,7 +31,6 @@ interface Dependencies {
|
||||
operatingSystemTheme: IComputedValue<Theme>;
|
||||
askUserForFilePaths: AskUserForFilePaths;
|
||||
emitAppEvent: EmitAppEvent;
|
||||
createResourceApplier: CreateResourceApplier;
|
||||
}
|
||||
|
||||
export const setupIpcMainHandlers = ({
|
||||
@@ -42,7 +40,6 @@ export const setupIpcMainHandlers = ({
|
||||
operatingSystemTheme,
|
||||
askUserForFilePaths,
|
||||
emitAppEvent,
|
||||
createResourceApplier,
|
||||
}: Dependencies) => {
|
||||
ipcMainHandle(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => {
|
||||
return ClusterStore.getInstance()
|
||||
@@ -71,44 +68,6 @@ export const setupIpcMainHandlers = ({
|
||||
}
|
||||
});
|
||||
|
||||
ipcMainHandle(clusterKubectlApplyAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => {
|
||||
emitAppEvent({ name: "cluster", action: "kubectl-apply-all" });
|
||||
const cluster = ClusterStore.getInstance().getById(clusterId);
|
||||
|
||||
if (cluster) {
|
||||
const applier = createResourceApplier(cluster);
|
||||
|
||||
try {
|
||||
const stdout = await applier.kubectlApplyAll(resources, extraArgs);
|
||||
|
||||
return { stdout };
|
||||
} catch (error: any) {
|
||||
return { stderr: error };
|
||||
}
|
||||
} else {
|
||||
throw `${clusterId} is not a valid cluster id`;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMainHandle(clusterKubectlDeleteAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => {
|
||||
emitAppEvent({ name: "cluster", action: "kubectl-delete-all" });
|
||||
const cluster = ClusterStore.getInstance().getById(clusterId);
|
||||
|
||||
if (cluster) {
|
||||
const applier = createResourceApplier(cluster);
|
||||
|
||||
try {
|
||||
const stdout = await applier.kubectlDeleteAll(resources, extraArgs);
|
||||
|
||||
return { stdout };
|
||||
} catch (error: any) {
|
||||
return { stderr: error };
|
||||
}
|
||||
} else {
|
||||
throw `${clusterId} is not a valid cluster id`;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMainHandle(windowActionHandleChannel, (event, action) => handleWindowAction(action));
|
||||
|
||||
ipcMainOn(windowLocationChangedChannel, () => onLocationChange());
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
|
||||
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
|
||||
import { kubectlApplyAllChannel } from "../../common/kube-helpers/channels";
|
||||
import createResourceApplierInjectable from "../resource-applier/create-resource-applier.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
|
||||
|
||||
const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: kubectlApplyAllChannel,
|
||||
handler: (di) => {
|
||||
const getClusterById = di.inject(getClusterByIdInjectable);
|
||||
const emitAppEvent = di.inject(emitAppEventInjectable);
|
||||
const createResourceApplier = di.inject(createResourceApplierInjectable);
|
||||
|
||||
return async ({
|
||||
clusterId,
|
||||
extraArgs,
|
||||
resources,
|
||||
}) => {
|
||||
emitAppEvent({ name: "cluster", action: "kubectl-apply-all" });
|
||||
const cluster = getClusterById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `No cluster found for clusterId="${clusterId}"`,
|
||||
};
|
||||
}
|
||||
|
||||
return createResourceApplier(cluster).kubectlApplyAll(resources, extraArgs);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default kubectlApplyAllChannelHandlerInjectable;
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
|
||||
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
|
||||
import { kubectlDeleteAllChannel } from "../../common/kube-helpers/channels";
|
||||
import createResourceApplierInjectable from "../resource-applier/create-resource-applier.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
|
||||
|
||||
const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: kubectlDeleteAllChannel,
|
||||
handler: (di) => {
|
||||
const emitAppEvent = di.inject(emitAppEventInjectable);
|
||||
const getClusterById = di.inject(getClusterByIdInjectable);
|
||||
const createResourceApplier = di.inject(createResourceApplierInjectable);
|
||||
|
||||
return async ({
|
||||
clusterId,
|
||||
extraArgs,
|
||||
resources,
|
||||
}) => {
|
||||
emitAppEvent({ name: "cluster", action: "kubectl-delete-all" });
|
||||
|
||||
const cluster = getClusterById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `No cluster found for clusterId="${clusterId}"`,
|
||||
};
|
||||
}
|
||||
|
||||
return createResourceApplier(cluster).kubectlDeleteAll(resources, extraArgs);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default kubectlDeleteAllChannelHandlerInjectable;
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 { kubectlApplyAllInjectionToken } from "../../common/kube-helpers/channels";
|
||||
import kubectlApplyAllChannelHandlerInjectable from "./apply-all-handler.injectable";
|
||||
|
||||
const kubectlApplyAllInjectable = getInjectable({
|
||||
id: "kubectl-apply-all",
|
||||
instantiate: (di) => {
|
||||
const channelHandler = di.inject(kubectlApplyAllChannelHandlerInjectable);
|
||||
|
||||
return async (req) => channelHandler.handler(req);
|
||||
},
|
||||
injectionToken: kubectlApplyAllInjectionToken,
|
||||
});
|
||||
|
||||
export default kubectlApplyAllInjectable;
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 { kubectlDeleteAllInjectionToken } from "../../common/kube-helpers/channels";
|
||||
import kubectlDeleteAllChannelHandlerInjectable from "./delete-all-handler.injectable";
|
||||
|
||||
const kubectlDeleteAllInjectable = getInjectable({
|
||||
id: "kubectl-delete-all",
|
||||
instantiate: (di) => {
|
||||
const channel = di.inject(kubectlDeleteAllChannelHandlerInjectable);
|
||||
|
||||
return async (req) => channel.handler(req);
|
||||
},
|
||||
injectionToken: kubectlDeleteAllInjectionToken,
|
||||
});
|
||||
|
||||
export default kubectlDeleteAllInjectable;
|
||||
@@ -14,6 +14,7 @@ import type { WriteFile } from "../../common/fs/write-file.injectable";
|
||||
import type { DeleteFile } from "../../common/fs/delete-file.injectable";
|
||||
import type { ExecFile } from "../../common/fs/exec-file.injectable";
|
||||
import type { JoinPaths } from "../../common/path/join-paths.injectable";
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
export interface ResourceApplierDependencies {
|
||||
emitAppEvent: EmitAppEvent;
|
||||
@@ -66,13 +67,13 @@ export class ResourceApplier {
|
||||
throw result.error.stderr || result.error.message;
|
||||
}
|
||||
|
||||
async create(resource: string): Promise<string> {
|
||||
async create(resource: string): Promise<AsyncResult<string, string>> {
|
||||
this.dependencies.emitAppEvent({ name: "resource", action: "apply" });
|
||||
|
||||
return this.kubectlApply(this.sanitizeObject(resource));
|
||||
}
|
||||
|
||||
protected async kubectlApply(content: string): Promise<string> {
|
||||
protected async kubectlApply(content: string): Promise<AsyncResult<string, string>> {
|
||||
const kubectl = await this.cluster.ensureKubectl();
|
||||
const kubectlPath = await kubectl.getPath();
|
||||
const proxyKubeconfigPath = await this.cluster.getProxyKubeconfigPath();
|
||||
@@ -99,24 +100,27 @@ export class ResourceApplier {
|
||||
const result = await this.dependencies.execFile(kubectlPath, args);
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response;
|
||||
return result;
|
||||
}
|
||||
|
||||
throw result.error.stderr || result.error.message;
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: result.error.stderr || result.error.message,
|
||||
};
|
||||
} finally {
|
||||
await this.dependencies.deleteFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public async kubectlApplyAll(resources: string[], extraArgs = ["-o", "json"]): Promise<string> {
|
||||
public async kubectlApplyAll(resources: string[], extraArgs = ["-o", "json"]): Promise<AsyncResult<string, string>> {
|
||||
return this.kubectlCmdAll("apply", resources, extraArgs);
|
||||
}
|
||||
|
||||
public async kubectlDeleteAll(resources: string[], extraArgs?: string[]): Promise<string> {
|
||||
public async kubectlDeleteAll(resources: string[], extraArgs?: string[]): Promise<AsyncResult<string, string>> {
|
||||
return this.kubectlCmdAll("delete", resources, extraArgs);
|
||||
}
|
||||
|
||||
protected async kubectlCmdAll(subCmd: string, resources: string[], parentArgs: string[] = []): Promise<string> {
|
||||
protected async kubectlCmdAll(subCmd: string, resources: string[], parentArgs: string[] = []): Promise<AsyncResult<string, string>> {
|
||||
const kubectl = await this.cluster.ensureKubectl();
|
||||
const kubectlPath = await kubectl.getPath();
|
||||
const proxyKubeconfigPath = await this.cluster.getProxyKubeconfigPath();
|
||||
@@ -138,14 +142,17 @@ export class ResourceApplier {
|
||||
const result = await this.dependencies.execFile(kubectlPath, args);
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response;
|
||||
return result;
|
||||
}
|
||||
|
||||
this.dependencies.logger.error(`[RESOURCE-APPLIER] kubectl errored: ${result.error.message}`);
|
||||
|
||||
const splitError = result.error.stderr.split(`.yaml": `);
|
||||
|
||||
throw splitError[1] || result.error.message;
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: splitError[1] || result.error.message,
|
||||
};
|
||||
}
|
||||
|
||||
protected sanitizeObject(resource: string) {
|
||||
|
||||
Reference in new issue
Block a user