mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Remove a lot of usages of legacy globals (#6825)
* Remove all usages of legacy global logger Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global storageClassApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global serviceApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global secretApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global resourceQuotaApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global persistentVolumeClaimApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global nodeApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global networkPolicyApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix formatting Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global configMapApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global jobApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global cronJobApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global podApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global roleApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove exports of NonInjected components - To improve auto-complete Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global catalogEntityRegistry Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add lint against using legacy global works Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix lint in KubeObject file Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global catalogCategoryRegistry Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global navigation Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global navigate Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unneeded index file Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global customResourceDefinitionStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global eventStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global podSecurityPolicyStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global storageClassStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global persistentVolumeStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global clusterRoleBindingStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global clusterRoleStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global roleBindingStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move files around Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global roleStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global serviceAccountStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usages of legacy global podStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove final uses of asLegacyGlobalForExtensionApi in application code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix lint rule and start fixing lint errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make listHelmReleases injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make installHelmChart injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make deleteHelmRelease injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make getHelmReleaseValues injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make getHelmReleaseHistory injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make rollbackHelmRelease injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unnecessary overrides from getDiForUnitTesting Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override for logger Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override for history Signed-off-by: Sebastian Malton <sebastian@malton.name> * Cleanup typing around getting injectables within jest Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move some more overrides to global if needed Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override for forcusWindow Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix lint in KubeApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix lint in catalog/index.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove last usages of legacy global getDetailsUrl Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove last usages of legacy global showDetails Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add functions back to extension API Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove all uses of legacy global Notification functions Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove no longer existing export Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unnecessary overrides Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix injecting side effects by using more injectables Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix cluster role binding dialog Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix cluster role dialog Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix create service account dialog Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix history override Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make KubeApi consume its dependencies while not breaking the extension API Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix CephFs tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix user store tests by using override of config Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in hotbar store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add direct devDep of memfs Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in cluster store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in router tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in kube auth proxy tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in log resource selector tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in hotbar remove command tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in the select component tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove mock-fs as a dependency Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove no longer necessary mocks Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix namespace select filter tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of mockFs in the extension loader tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fixing edit-namespace-from-new-tab test Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix app paths tests by making the tests run in "production" mode Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove last vestiges of isTestEnv and the is* globals Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix delete-cluster-dialog tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix install-helm-chart-from-previously-opened-tab tests - Split out storage initialization to a runnable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unnecessary override of non side effect injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix disable-kube-object-detail-items-when-cluster-is-not-relevant tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix reactively-hide-kube-object-detail-item tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix lint Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix sidebar-and-tab-navigation-for-core tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove need to override lensLocalStoragePath in tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace more overrides with global ones Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix typings Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove no longer needed technical test Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
900a8bbda3
commit
2b33d5eed6
530 files changed
+11320
-5399
No files matched your search
@@ -3,6 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import defaultWebsocketApiParamsInjectable from "../default-websocket-api-params.injectable";
|
||||
import type { WebSocketEvents } from "../websocket-api";
|
||||
import { WebSocketApi } from "../websocket-api";
|
||||
|
||||
@@ -16,7 +18,11 @@ describe("WebsocketApi tests", () => {
|
||||
let api: TestWebSocketApi;
|
||||
|
||||
beforeEach(() => {
|
||||
api = new TestWebSocketApi({});
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
api = new TestWebSocketApi({
|
||||
defaultParams: di.inject(defaultWebsocketApiParamsInjectable),
|
||||
}, {});
|
||||
});
|
||||
|
||||
describe("before connection", () => {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import catalogCategoryRegistryInjectable from "../../common/catalog/category-registry.injectable";
|
||||
import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
|
||||
export type { CategoryFilter } from "../../common/catalog";
|
||||
|
||||
export const catalogCategoryRegistry = asLegacyGlobalForExtensionApi(catalogCategoryRegistryInjectable);
|
||||
@@ -4,8 +4,10 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import hostedClusterIdInjectable from "../cluster-frame-context/hosted-cluster-id.injectable";
|
||||
import type { TerminalApiQuery } from "./terminal-api";
|
||||
import defaultWebsocketApiParamsInjectable from "./default-websocket-api-params.injectable";
|
||||
import type { TerminalApiDependencies, TerminalApiQuery } from "./terminal-api";
|
||||
import { TerminalApi } from "./terminal-api";
|
||||
|
||||
export type CreateTerminalApi = (query: TerminalApiQuery) => TerminalApi;
|
||||
@@ -14,12 +16,17 @@ const createTerminalApiInjectable = getInjectable({
|
||||
id: "create-terminal-api",
|
||||
instantiate: (di): CreateTerminalApi => {
|
||||
const hostedClusterId = di.inject(hostedClusterIdInjectable);
|
||||
const deps: Omit<TerminalApiDependencies, "hostedClusterId"> = {
|
||||
logger: di.inject(loggerInjectable),
|
||||
defaultParams: di.inject(defaultWebsocketApiParamsInjectable),
|
||||
};
|
||||
|
||||
return (query) => {
|
||||
assert(hostedClusterId, "Can only create terminal APIs within a cluster frame");
|
||||
|
||||
return new TerminalApi({
|
||||
hostedClusterId,
|
||||
...deps,
|
||||
}, query);
|
||||
};
|
||||
},
|
||||
|
||||
@@ -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 } from "@ogre-tools/injectable";
|
||||
import type { TerminalMessage } from "../../common/terminal/channels";
|
||||
import { TerminalChannels } from "../../common/terminal/channels";
|
||||
import isDevelopmentInjectable from "../../common/vars/is-development.injectable";
|
||||
|
||||
export type DefaultWebsocketApiParams = ReturnType<typeof defaultWebsocketApiParamsInjectable.instantiate>;
|
||||
|
||||
const defaultWebsocketApiParamsInjectable = getInjectable({
|
||||
id: "default-websocket-api-params",
|
||||
instantiate: (di) => ({
|
||||
logging: di.inject(isDevelopmentInjectable),
|
||||
reconnectDelay: 10,
|
||||
flushOnOpen: true,
|
||||
pingMessage: JSON.stringify({ type: TerminalChannels.PING } as TerminalMessage),
|
||||
}),
|
||||
});
|
||||
|
||||
export default defaultWebsocketApiParamsInjectable;
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { WebSocketEvents } from "./websocket-api";
|
||||
import type { WebSocketApiDependencies, WebSocketEvents } from "./websocket-api";
|
||||
import { WebSocketApi } from "./websocket-api";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import url from "url";
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import { ipcRenderer } from "electron";
|
||||
import logger from "../../common/logger";
|
||||
import type { Logger } from "../../common/logger";
|
||||
import { once } from "lodash";
|
||||
import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels";
|
||||
|
||||
@@ -36,8 +36,9 @@ export interface TerminalEvents extends WebSocketEvents {
|
||||
connected: () => void;
|
||||
}
|
||||
|
||||
export interface TerminalApiDependencies {
|
||||
export interface TerminalApiDependencies extends WebSocketApiDependencies {
|
||||
readonly hostedClusterId: string;
|
||||
readonly logger: Logger;
|
||||
}
|
||||
|
||||
export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
||||
@@ -46,7 +47,7 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
||||
@observable public isReady = false;
|
||||
|
||||
constructor(protected readonly dependencies: TerminalApiDependencies, protected readonly query: TerminalApiQuery) {
|
||||
super({
|
||||
super(dependencies, {
|
||||
flushOnOpen: false,
|
||||
pingInterval: 30,
|
||||
});
|
||||
@@ -145,11 +146,11 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
||||
this.emit("connected");
|
||||
break;
|
||||
default:
|
||||
logger.warn(`[TERMINAL-API]: unknown or unhandleable message type`, message);
|
||||
this.dependencies.logger.warn(`[TERMINAL-API]: unknown or unhandleable message type`, message);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[TERMINAL-API]: failed to handle message`, error);
|
||||
this.dependencies.logger.error(`[TERMINAL-API]: failed to handle message`, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,8 @@ import { observable, makeObservable } from "mobx";
|
||||
import EventEmitter from "events";
|
||||
import type TypedEventEmitter from "typed-emitter";
|
||||
import type { Arguments } from "typed-emitter";
|
||||
import { isDevelopment } from "../../common/vars";
|
||||
import type { Defaulted } from "../utils";
|
||||
import { TerminalChannels, type TerminalMessage } from "../../common/terminal/channels";
|
||||
import type { DefaultWebsocketApiParams } from "./default-websocket-api-params.injectable";
|
||||
|
||||
interface WebsocketApiParams {
|
||||
/**
|
||||
@@ -64,27 +63,24 @@ export interface WebSocketEvents {
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
export interface WebSocketApiDependencies {
|
||||
readonly defaultParams: DefaultWebsocketApiParams;
|
||||
}
|
||||
|
||||
export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter as { new<T>(): TypedEventEmitter<T> })<Events> {
|
||||
protected socket: WebSocket | null = null;
|
||||
protected pendingCommands: string[] = [];
|
||||
protected reconnectTimer?: number;
|
||||
protected pingTimer?: number;
|
||||
protected params: Defaulted<WebsocketApiParams, keyof typeof WebSocketApi["defaultParams"]>;
|
||||
protected params: Defaulted<WebsocketApiParams, keyof DefaultWebsocketApiParams>;
|
||||
|
||||
@observable readyState = WebSocketApiState.PENDING;
|
||||
|
||||
private static readonly defaultParams = {
|
||||
logging: isDevelopment,
|
||||
reconnectDelay: 10,
|
||||
flushOnOpen: true,
|
||||
pingMessage: JSON.stringify({ type: TerminalChannels.PING } as TerminalMessage),
|
||||
};
|
||||
|
||||
constructor(params: WebsocketApiParams) {
|
||||
constructor(protected readonly dependencies: WebSocketApiDependencies, params: WebsocketApiParams) {
|
||||
super();
|
||||
makeObservable(this);
|
||||
this.params = {
|
||||
...WebSocketApi.defaultParams,
|
||||
...this.dependencies.defaultParams,
|
||||
...params,
|
||||
};
|
||||
const { pingInterval } = this.params;
|
||||
|
||||
@@ -7,11 +7,14 @@ import autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manag
|
||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import { CustomResourceStore } from "../../../common/k8s-api/api-manager/resource.store";
|
||||
import type { CustomResourceDefinition } from "../../../common/k8s-api/endpoints";
|
||||
import type { KubeApiDependencies } from "../../../common/k8s-api/kube-api";
|
||||
import { KubeApi } from "../../../common/k8s-api/kube-api";
|
||||
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import { beforeClusterFrameStartsSecondInjectionToken } from "../tokens";
|
||||
import type { KubeObjectStoreDependencies } from "../../../common/k8s-api/kube-object.store";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import maybeKubeApiInjectable from "../../../common/k8s-api/maybe-kube-api.injectable";
|
||||
|
||||
const setupAutoRegistrationInjectable = getInjectable({
|
||||
id: "setup-auto-registration",
|
||||
@@ -21,8 +24,13 @@ const setupAutoRegistrationInjectable = getInjectable({
|
||||
const autoRegistrationEmitter = di.inject(autoRegistrationEmitterInjectable);
|
||||
const beforeApiManagerInitializationCrds: CustomResourceDefinition[] = [];
|
||||
const beforeApiManagerInitializationApis: KubeApi[] = [];
|
||||
const deps: KubeObjectStoreDependencies = {
|
||||
const kubeApiDependencies: KubeApiDependencies = {
|
||||
logger: di.inject(loggerInjectable),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
};
|
||||
const kubeObjectStoreDependencies: KubeObjectStoreDependencies = {
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
};
|
||||
let initialized = false;
|
||||
|
||||
@@ -40,7 +48,7 @@ const setupAutoRegistrationInjectable = getInjectable({
|
||||
return rawApi;
|
||||
}
|
||||
|
||||
const api = new KubeApi({ objectConstructor });
|
||||
const api = new KubeApi(kubeApiDependencies, { objectConstructor });
|
||||
|
||||
apiManager.registerApi(api);
|
||||
|
||||
@@ -48,7 +56,7 @@ const setupAutoRegistrationInjectable = getInjectable({
|
||||
})();
|
||||
|
||||
if (!apiManager.getStore(api)) {
|
||||
apiManager.registerStore(new CustomResourceStore(deps, api));
|
||||
apiManager.registerStore(new CustomResourceStore(kubeObjectStoreDependencies, api));
|
||||
}
|
||||
};
|
||||
const autoInitKubeApi = (api: KubeApi) => {
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ const setupKubernetesClusterContextMenuOpenInjectable = getInjectable({
|
||||
if (result.error) {
|
||||
logger.error("[KUBERNETES-CLUSTER]: failed to parse kubeconfig file", result.error);
|
||||
} else {
|
||||
openDeleteClusterDialog({ cluster, config: result.config });
|
||||
openDeleteClusterDialog(result.config, cluster);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import extensionLoaderInjectable from "../extensions/extension-loader/extension-loader.injectable";
|
||||
import extensionDiscoveryInjectable from "../extensions/extension-discovery/extension-discovery.injectable";
|
||||
import extensionInstallationStateStoreInjectable from "../extensions/extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import initRootFrameInjectable from "./frames/root-frame/init-root-frame/init-root-frame.injectable";
|
||||
import initRootFrameInjectable from "./frames/root-frame/init-root-frame.injectable";
|
||||
import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable";
|
||||
import { Router } from "react-router";
|
||||
import historyInjectable from "./navigation/history.injectable";
|
||||
|
||||
@@ -16,17 +16,19 @@ import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers"
|
||||
import { docsUrl } from "../../../common/vars";
|
||||
import { isDefined, iter } from "../../utils";
|
||||
import { Button } from "../button";
|
||||
import { Notifications } from "../notifications";
|
||||
import type { ShowNotification } from "../notifications";
|
||||
import { SettingLayout } from "../layout/setting-layout";
|
||||
import { MonacoEditor } from "../monaco-editor";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import getCustomKubeConfigDirectoryInjectable from "../../../common/app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
|
||||
import getCustomKubeConfigFilePathInjectable from "../../../common/app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
|
||||
import type { NavigateToCatalog } from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
|
||||
import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
|
||||
import type { EmitAppEvent } from "../../../common/app-event-bus/emit-event.injectable";
|
||||
import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
|
||||
import type { GetDirnameOfPath } from "../../../common/path/get-dirname.injectable";
|
||||
import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable";
|
||||
import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable";
|
||||
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
|
||||
|
||||
interface Option {
|
||||
config: KubeConfig;
|
||||
@@ -38,6 +40,8 @@ interface Dependencies {
|
||||
navigateToCatalog: NavigateToCatalog;
|
||||
getDirnameOfPath: GetDirnameOfPath;
|
||||
emitAppEvent: EmitAppEvent;
|
||||
showSuccessNotification: ShowNotification;
|
||||
showErrorNotification: ShowNotification;
|
||||
}
|
||||
|
||||
function getContexts(config: KubeConfig): Map<string, Option> {
|
||||
@@ -97,11 +101,11 @@ class NonInjectedAddCluster extends React.Component<Dependencies> {
|
||||
await fse.ensureDir(this.props.getDirnameOfPath(absPath));
|
||||
await fse.writeFile(absPath, this.customConfig.trim(), { encoding: "utf-8", mode: 0o600 });
|
||||
|
||||
Notifications.ok(`Successfully added ${this.kubeContexts.size} new cluster(s)`);
|
||||
this.props.showSuccessNotification(`Successfully added ${this.kubeContexts.size} new cluster(s)`);
|
||||
|
||||
return this.props.navigateToCatalog();
|
||||
} catch (error) {
|
||||
Notifications.error(`Failed to add clusters: ${error}`);
|
||||
this.props.showErrorNotification(`Failed to add clusters: ${error}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -159,9 +163,11 @@ class NonInjectedAddCluster extends React.Component<Dependencies> {
|
||||
|
||||
export const AddCluster = withInjectables<Dependencies>(NonInjectedAddCluster, {
|
||||
getProps: (di) => ({
|
||||
getCustomKubeConfigDirectory: di.inject(getCustomKubeConfigDirectoryInjectable),
|
||||
getCustomKubeConfigDirectory: di.inject(getCustomKubeConfigFilePathInjectable),
|
||||
navigateToCatalog: di.inject(navigateToCatalogInjectable),
|
||||
getDirnameOfPath: di.inject(getDirnameOfPathInjectable),
|
||||
emitAppEvent: di.inject(emitAppEventInjectable),
|
||||
showSuccessNotification: di.inject(showSuccessNotificationInjectable),
|
||||
showErrorNotification: di.inject(showErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -10,10 +10,13 @@ import { Icon } from "../icon";
|
||||
import { observer } from "mobx-react";
|
||||
import { observable, makeObservable, action } from "mobx";
|
||||
import { autoBind } from "../../../common/utils";
|
||||
import type { CatalogCategory, CatalogEntityAddMenuContext, CatalogEntityAddMenu } from "../../api/catalog-entity";
|
||||
import type { CatalogCategory, CatalogEntityAddMenu } from "../../api/catalog-entity";
|
||||
import { EventEmitter } from "events";
|
||||
import { navigate } from "../../navigation";
|
||||
import { catalogCategoryRegistry } from "../../api/catalog-category-registry";
|
||||
import type { CatalogCategoryRegistry } from "../../../common/catalog";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import catalogCategoryRegistryInjectable from "../../../common/catalog/category-registry.injectable";
|
||||
import type { Navigate } from "../../navigation/navigate.injectable";
|
||||
import navigateInjectable from "../../navigation/navigate.injectable";
|
||||
|
||||
export interface CatalogAddButtonProps {
|
||||
category: CatalogCategory;
|
||||
@@ -21,12 +24,17 @@ export interface CatalogAddButtonProps {
|
||||
|
||||
type CategoryId = string;
|
||||
|
||||
interface Dependencies {
|
||||
catalogCategoryRegistry: CatalogCategoryRegistry;
|
||||
navigate: Navigate;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
|
||||
class NonInjectedCatalogAddButton extends React.Component<CatalogAddButtonProps & Dependencies> {
|
||||
@observable protected isOpen = false;
|
||||
@observable menuItems = new Map<CategoryId, CatalogEntityAddMenu[]>();
|
||||
|
||||
constructor(props: CatalogAddButtonProps) {
|
||||
constructor(props: CatalogAddButtonProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
@@ -43,7 +51,7 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
|
||||
}
|
||||
|
||||
get categories() {
|
||||
return catalogCategoryRegistry.filteredItems;
|
||||
return this.props.catalogCategoryRegistry.filteredItems;
|
||||
}
|
||||
|
||||
@action
|
||||
@@ -61,12 +69,11 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
|
||||
updateCategoryItems = action((category: CatalogCategory) => {
|
||||
if (category instanceof EventEmitter) {
|
||||
const menuItems: CatalogEntityAddMenu[] = [];
|
||||
const context: CatalogEntityAddMenuContext = {
|
||||
navigate: (url: string) => navigate(url),
|
||||
menuItems,
|
||||
};
|
||||
|
||||
category.emit("catalogAddMenu", context);
|
||||
category.emit("catalogAddMenu", {
|
||||
navigate: this.props.navigate,
|
||||
menuItems,
|
||||
});
|
||||
this.menuItems.set(category.getId(), menuItems);
|
||||
}
|
||||
});
|
||||
@@ -133,3 +140,11 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const CatalogAddButton = withInjectables<Dependencies, CatalogAddButtonProps>(NonInjectedCatalogAddButton, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
catalogCategoryRegistry: di.inject(catalogCategoryRegistryInjectable),
|
||||
navigate: di.inject(navigateInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -23,7 +23,7 @@ import type { EventStore } from "../+events/store";
|
||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import eventStoreInjectable from "../+events/store.injectable";
|
||||
import nodeStoreInjectable from "../+nodes/store.injectable";
|
||||
import type { PageParam } from "../../navigation";
|
||||
import type { PageParam } from "../../navigation/page-param";
|
||||
import type { ToggleKubeDetailsPane } from "../kube-detail-params/toggle-details.injectable";
|
||||
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
|
||||
import toggleKubeDetailsPaneInjectable from "../kube-detail-params/toggle-details.injectable";
|
||||
|
||||
+2
@@ -14,6 +14,7 @@ import assert from "assert";
|
||||
import nodeStoreInjectable from "../../+nodes/store.injectable";
|
||||
import requestClusterMetricsByNodeNamesInjectable from "../../../../common/k8s-api/endpoints/metrics.api/request-cluster-metrics-by-node-names.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
|
||||
const clusterOverviewStoreInjectable = getInjectable({
|
||||
id: "cluster-overview-store",
|
||||
@@ -34,6 +35,7 @@ const clusterOverviewStoreInjectable = getInjectable({
|
||||
nodeStore: di.inject(nodeStoreInjectable),
|
||||
requestClusterMetricsByNodeNames: di.inject(requestClusterMetricsByNodeNamesInjectable),
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, clusterApi);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -16,17 +16,19 @@ import type { HorizontalPodAutoscalerMetricSpec, HorizontalPodAutoscalerMetricTa
|
||||
import { HorizontalPodAutoscaler, HpaMetricType } from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface HpaDetailsProps extends KubeObjectDetailsProps<HorizontalPodAutoscaler> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
apiManager: ApiManager;
|
||||
logger: Logger;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
}
|
||||
|
||||
@@ -104,7 +106,7 @@ class NonInjectedHpaDetails extends React.Component<HpaDetailsProps & Dependenci
|
||||
}
|
||||
|
||||
render() {
|
||||
const { object: hpa, apiManager, getDetailsUrl } = this.props;
|
||||
const { object: hpa, apiManager, getDetailsUrl, logger } = this.props;
|
||||
|
||||
if (!hpa) {
|
||||
return null;
|
||||
@@ -172,5 +174,6 @@ export const HpaDetails = withInjectables<Dependencies, HpaDetailsProps>(NonInje
|
||||
...props,
|
||||
apiManager: di.inject(apiManagerInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import horizontalPodAutoscalerApiInjectable from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { HorizontalPodAutoscalerStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const horizontalPodAutoscalerStoreInjectable = getInjectable({
|
||||
|
||||
return new HorizontalPodAutoscalerStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import leaseApiInjectable from "../../../common/k8s-api/endpoints/lease.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { LeaseStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const leaseStoreInjectable = getInjectable({
|
||||
|
||||
return new LeaseStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -12,7 +12,9 @@ import type { LimitRangeItem } from "../../../common/k8s-api/endpoints/limit-ran
|
||||
import { LimitPart, LimitRange, Resource } from "../../../common/k8s-api/endpoints/limit-range.api";
|
||||
import { DrawerItem } from "../drawer/drawer-item";
|
||||
import { Badge } from "../badge";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface LimitRangeDetailsProps extends KubeObjectDetailsProps<LimitRange> {
|
||||
}
|
||||
@@ -51,10 +53,14 @@ function renderLimitDetails(limits: LimitRangeItem[], resources: Resource[]) {
|
||||
));
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class LimitRangeDetails extends React.Component<LimitRangeDetailsProps> {
|
||||
class NonInjectedLimitRangeDetails extends React.Component<LimitRangeDetailsProps & Dependencies> {
|
||||
render() {
|
||||
const { object: limitRange } = this.props;
|
||||
const { object: limitRange, logger } = this.props;
|
||||
|
||||
if (!limitRange) {
|
||||
return null;
|
||||
@@ -97,3 +103,10 @@ export class LimitRangeDetails extends React.Component<LimitRangeDetailsProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const LimitRangeDetails = withInjectables<Dependencies, LimitRangeDetailsProps>(NonInjectedLimitRangeDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import limitRangeApiInjectable from "../../../common/k8s-api/endpoints/limit-range.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { LimitRangeStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const limitRangeStoreInjectable = getInjectable({
|
||||
|
||||
return new LimitRangeStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import configMapApiInjectable from "../../../common/k8s-api/endpoints/config-map.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { ConfigMapStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const configMapStoreInjectable = getInjectable({
|
||||
|
||||
return new ConfigMapStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
+16
-3
@@ -11,13 +11,19 @@ import { DrawerItem } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { PodDisruptionBudget } from "../../../common/k8s-api/endpoints";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface PodDisruptionBudgetDetailsProps extends KubeObjectDetailsProps<PodDisruptionBudget> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PodDisruptionBudgetDetails extends React.Component<PodDisruptionBudgetDetailsProps> {
|
||||
class NonInjectedPodDisruptionBudgetDetails extends React.Component<PodDisruptionBudgetDetailsProps & Dependencies> {
|
||||
|
||||
render() {
|
||||
const { object: pdb } = this.props;
|
||||
@@ -27,7 +33,7 @@ export class PodDisruptionBudgetDetails extends React.Component<PodDisruptionBud
|
||||
}
|
||||
|
||||
if (!(pdb instanceof PodDisruptionBudget)) {
|
||||
logger.error("[PodDisruptionBudgetDetails]: passed object that is not an instanceof PodDisruptionBudget", pdb);
|
||||
this.props.logger.error("[PodDisruptionBudgetDetails]: passed object that is not an instanceof PodDisruptionBudget", pdb);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -64,3 +70,10 @@ export class PodDisruptionBudgetDetails extends React.Component<PodDisruptionBud
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PodDisruptionBudgetDetails = withInjectables<Dependencies, PodDisruptionBudgetDetailsProps>(NonInjectedPodDisruptionBudgetDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import podDisruptionBudgetApiInjectable from "../../../common/k8s-api/endpoints/pod-disruption-budget.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { PodDisruptionBudgetStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const podDisruptionBudgetStoreInjectable = getInjectable({
|
||||
|
||||
return new PodDisruptionBudgetStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import priorityClassApiInjectable from "../../../common/k8s-api/endpoints/priority-class.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { PriorityClassStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const priorityClassStoreInjectable = getInjectable({
|
||||
|
||||
return new PriorityClassStore({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -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 { action } from "mobx";
|
||||
import addQuotaDialogOpenStateInjectable from "./open-state.injectable";
|
||||
|
||||
const closeAddQuotaDialogInjectable = getInjectable({
|
||||
id: "close-add-quota-dialog",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(addQuotaDialogOpenStateInjectable);
|
||||
|
||||
return action(() => state.set(false));
|
||||
},
|
||||
});
|
||||
|
||||
export default closeAddQuotaDialogInjectable;
|
||||
@@ -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 addQuotaDialogOpenStateInjectable from "./open-state.injectable";
|
||||
|
||||
const isAddQuotaDialogOpenInjectable = getInjectable({
|
||||
id: "is-add-quota-dialog-open",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(addQuotaDialogOpenStateInjectable);
|
||||
|
||||
return computed(() => state.get());
|
||||
},
|
||||
});
|
||||
|
||||
export default isAddQuotaDialogOpenInjectable;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 { observable } from "mobx";
|
||||
|
||||
const addQuotaDialogOpenStateInjectable = getInjectable({
|
||||
id: "add-quota-dialog-open-state",
|
||||
instantiate: () => observable.box(false),
|
||||
});
|
||||
|
||||
export default addQuotaDialogOpenStateInjectable;
|
||||
@@ -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 { action } from "mobx";
|
||||
import addQuotaDialogOpenStateInjectable from "./open-state.injectable";
|
||||
|
||||
const openAddQuotaDialogInjectable = getInjectable({
|
||||
id: "open-add-quota-dialog",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(addQuotaDialogOpenStateInjectable);
|
||||
|
||||
return action(() => state.set(true));
|
||||
},
|
||||
});
|
||||
|
||||
export default openAddQuotaDialogInjectable;
|
||||
File renamed without changes.
+65
-54
@@ -3,54 +3,63 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import "./add-quota-dialog.scss";
|
||||
import "./view.scss";
|
||||
|
||||
import React from "react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { computed, observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { DialogProps } from "../dialog";
|
||||
import { Dialog } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
import { Input } from "../input";
|
||||
import { systemName } from "../input/input_validators";
|
||||
import type { IResourceQuotaValues } from "../../../common/k8s-api/endpoints";
|
||||
import { resourceQuotaApi } from "../../../common/k8s-api/endpoints";
|
||||
import { Select } from "../select";
|
||||
import { Icon } from "../icon";
|
||||
import { Button } from "../button";
|
||||
import { Notifications } from "../notifications";
|
||||
import { NamespaceSelect } from "../+namespaces/namespace-select";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import type { DialogProps } from "../../dialog";
|
||||
import { Dialog } from "../../dialog";
|
||||
import { Wizard, WizardStep } from "../../wizard";
|
||||
import { Input } from "../../input";
|
||||
import { systemName } from "../../input/input_validators";
|
||||
import type { IResourceQuotaValues, ResourceQuotaApi } from "../../../../common/k8s-api/endpoints";
|
||||
import { Select } from "../../select";
|
||||
import { Icon } from "../../icon";
|
||||
import { Button } from "../../button";
|
||||
import { NamespaceSelect } from "../../+namespaces/namespace-select";
|
||||
import { SubTitle } from "../../layout/sub-title";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import closeAddQuotaDialogInjectable from "./close.injectable";
|
||||
import isAddQuotaDialogOpenInjectable from "./is-open.injectable";
|
||||
import resourceQuotaApiInjectable from "../../../../common/k8s-api/endpoints/resource-quota.api.injectable";
|
||||
import type { ShowCheckedErrorNotification } from "../../notifications/show-checked-error.injectable";
|
||||
import showCheckedErrorNotificationInjectable from "../../notifications/show-checked-error.injectable";
|
||||
|
||||
export interface AddQuotaDialogProps extends DialogProps {
|
||||
}
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
});
|
||||
interface Dependencies {
|
||||
resourceQuotaApi: ResourceQuotaApi;
|
||||
isAddQuotaDialogOpen: IComputedValue<boolean>;
|
||||
closeAddQuotaDialog: () => void;
|
||||
showCheckedErrorNotification: ShowCheckedErrorNotification;
|
||||
}
|
||||
|
||||
const defaultQuotas = JSON.stringify({
|
||||
"limits.cpu": "",
|
||||
"limits.memory": "",
|
||||
"requests.cpu": "",
|
||||
"requests.memory": "",
|
||||
"requests.storage": "",
|
||||
"persistentvolumeclaims": "",
|
||||
"count/pods": "",
|
||||
"count/persistentvolumeclaims": "",
|
||||
"count/services": "",
|
||||
"count/secrets": "",
|
||||
"count/configmaps": "",
|
||||
"count/replicationcontrollers": "",
|
||||
"count/deployments.apps": "",
|
||||
"count/replicasets.apps": "",
|
||||
"count/statefulsets.apps": "",
|
||||
"count/jobs.batch": "",
|
||||
"count/cronjobs.batch": "",
|
||||
"count/deployments.extensions": "",
|
||||
} as IResourceQuotaValues);
|
||||
|
||||
@observer
|
||||
export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
static defaultQuotas: IResourceQuotaValues = {
|
||||
"limits.cpu": "",
|
||||
"limits.memory": "",
|
||||
"requests.cpu": "",
|
||||
"requests.memory": "",
|
||||
"requests.storage": "",
|
||||
"persistentvolumeclaims": "",
|
||||
"count/pods": "",
|
||||
"count/persistentvolumeclaims": "",
|
||||
"count/services": "",
|
||||
"count/secrets": "",
|
||||
"count/configmaps": "",
|
||||
"count/replicationcontrollers": "",
|
||||
"count/deployments.apps": "",
|
||||
"count/replicasets.apps": "",
|
||||
"count/statefulsets.apps": "",
|
||||
"count/jobs.batch": "",
|
||||
"count/cronjobs.batch": "",
|
||||
"count/deployments.extensions": "",
|
||||
};
|
||||
class NonInjectedAddQuotaDialog extends React.Component<AddQuotaDialogProps & Dependencies> {
|
||||
|
||||
public defaultNamespace = "default";
|
||||
|
||||
@@ -58,21 +67,13 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
@observable quotaSelectValue: string | null = null;
|
||||
@observable quotaInputValue = "";
|
||||
@observable namespace: string | null = this.defaultNamespace;
|
||||
@observable quotas = AddQuotaDialog.defaultQuotas;
|
||||
@observable quotas: IResourceQuotaValues = JSON.parse(defaultQuotas);
|
||||
|
||||
constructor(props: AddQuotaDialogProps) {
|
||||
constructor(props: AddQuotaDialogProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
dialogState.isOpen = true;
|
||||
}
|
||||
|
||||
static close() {
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
@computed get quotaEntries() {
|
||||
return Object.entries(this.quotas)
|
||||
.filter(([, value]) => !!value?.trim());
|
||||
@@ -101,7 +102,7 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
};
|
||||
|
||||
close = () => {
|
||||
AddQuotaDialog.close();
|
||||
this.props.closeAddQuotaDialog();
|
||||
};
|
||||
|
||||
reset = () => {
|
||||
@@ -109,7 +110,7 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
this.quotaSelectValue = "";
|
||||
this.quotaInputValue = "";
|
||||
this.namespace = this.defaultNamespace;
|
||||
this.quotas = AddQuotaDialog.defaultQuotas;
|
||||
this.quotas = JSON.parse(defaultQuotas);
|
||||
};
|
||||
|
||||
addQuota = async () => {
|
||||
@@ -122,14 +123,14 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
try {
|
||||
const quotas = Object.fromEntries(this.quotaEntries);
|
||||
|
||||
await resourceQuotaApi.create({ namespace, name: quotaName }, {
|
||||
await this.props.resourceQuotaApi.create({ namespace, name: quotaName }, {
|
||||
spec: {
|
||||
hard: quotas,
|
||||
},
|
||||
});
|
||||
this.close();
|
||||
} catch (err) {
|
||||
Notifications.checkedError(err, "Unknown error occured while creating ResourceQuota");
|
||||
this.props.showCheckedErrorNotification(err, "Unknown error occured while creating ResourceQuota");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,14 +144,14 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { ...dialogProps } = this.props;
|
||||
const { closeAddQuotaDialog, isAddQuotaDialogOpen, resourceQuotaApi, ...dialogProps } = this.props;
|
||||
const header = <h5>Create ResourceQuota</h5>;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddQuotaDialog"
|
||||
isOpen={dialogState.isOpen}
|
||||
isOpen={isAddQuotaDialogOpen.get()}
|
||||
close={this.close}
|
||||
>
|
||||
<Wizard header={header} done={this.close}>
|
||||
@@ -244,3 +245,13 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const AddQuotaDialog = withInjectables<Dependencies, AddQuotaDialogProps>(NonInjectedAddQuotaDialog, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
closeAddQuotaDialog: di.inject(closeAddQuotaDialogInjectable),
|
||||
isAddQuotaDialogOpen: di.inject(isAddQuotaDialogOpenInjectable),
|
||||
resourceQuotaApi: di.inject(resourceQuotaApiInjectable),
|
||||
showCheckedErrorNotification: di.inject(showCheckedErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -13,7 +13,9 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { ResourceQuota } from "../../../common/k8s-api/endpoints/resource-quota.api";
|
||||
import { LineProgress } from "../line-progress";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface ResourceQuotaDetailsProps extends KubeObjectDetailsProps<ResourceQuota> {
|
||||
}
|
||||
@@ -75,8 +77,12 @@ function renderQuotas(quota: ResourceQuota): JSX.Element[] {
|
||||
});
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ResourceQuotaDetails extends React.Component<ResourceQuotaDetailsProps> {
|
||||
class NonInjectedResourceQuotaDetails extends React.Component<ResourceQuotaDetailsProps & Dependencies> {
|
||||
render() {
|
||||
const { object: quota } = this.props;
|
||||
|
||||
@@ -85,7 +91,7 @@ export class ResourceQuotaDetails extends React.Component<ResourceQuotaDetailsPr
|
||||
}
|
||||
|
||||
if (!(quota instanceof ResourceQuota)) {
|
||||
logger.error("[ResourceQuotaDetails]: passed object that is not an instanceof ResourceQuota", quota);
|
||||
this.props.logger.error("[ResourceQuotaDetails]: passed object that is not an instanceof ResourceQuota", quota);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -125,3 +131,10 @@ export class ResourceQuotaDetails extends React.Component<ResourceQuotaDetailsPr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ResourceQuotaDetails = withInjectables<Dependencies, ResourceQuotaDetailsProps>(NonInjectedResourceQuotaDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -8,7 +8,7 @@ import "./resource-quotas.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||
import { AddQuotaDialog } from "./add-quota-dialog";
|
||||
import { AddQuotaDialog } from "./add-dialog/view";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
@@ -18,6 +18,7 @@ import type { FilterByNamespace } from "../+namespaces/namespace-select-filter-m
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import filterByNamespaceInjectable from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
import resourceQuotaStoreInjectable from "./store.injectable";
|
||||
import openAddQuotaDialogInjectable from "./add-dialog/open.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@@ -28,6 +29,7 @@ enum columnId {
|
||||
interface Dependencies {
|
||||
resourceQuotaStore: ResourceQuotaStore;
|
||||
filterByNamespace: FilterByNamespace;
|
||||
openAddQuotaDialog: () => void;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -69,7 +71,7 @@ class NonInjectedResourceQuotas extends React.Component<Dependencies> {
|
||||
<KubeObjectAge key="age" object={resourceQuota} />,
|
||||
]}
|
||||
addRemoveButtons={{
|
||||
onAdd: () => AddQuotaDialog.open(),
|
||||
onAdd: this.props.openAddQuotaDialog,
|
||||
addTooltip: "Create new ResourceQuota",
|
||||
}}
|
||||
/>
|
||||
@@ -84,5 +86,6 @@ export const ResourceQuotas = withInjectables<Dependencies>(NonInjectedResourceQ
|
||||
...props,
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
resourceQuotaStore: di.inject(resourceQuotaStoreInjectable),
|
||||
openAddQuotaDialog: di.inject(openAddQuotaDialogInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import resourceQuotaApiInjectable from "../../../common/k8s-api/endpoints/resource-quota.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { ResourceQuotaStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const resourceQuotaStoreInjectable = getInjectable({
|
||||
|
||||
return new ResourceQuotaStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import runtimeClassApiInjectable from "../../../common/k8s-api/endpoints/runtime-class.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { RuntimeClassStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const runtimeClassStoreInjectable = getInjectable({
|
||||
|
||||
return new RuntimeClassStore({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -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 { action } from "mobx";
|
||||
import addSecretDialogOpenStateInjectable from "./state.injectable";
|
||||
|
||||
const closeAddSecretDialogInjectable = getInjectable({
|
||||
id: "close-add-secret-dialog",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(addSecretDialogOpenStateInjectable);
|
||||
|
||||
return action(() => state.set(false));
|
||||
},
|
||||
});
|
||||
|
||||
export default closeAddSecretDialogInjectable;
|
||||
@@ -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 addSecretDialogOpenStateInjectable from "./state.injectable";
|
||||
|
||||
const isAddSecretDialogOpenInjectable = getInjectable({
|
||||
id: "is-add-secret-dialog-open",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(addSecretDialogOpenStateInjectable);
|
||||
|
||||
return computed(() => state.get());
|
||||
},
|
||||
});
|
||||
|
||||
export default isAddSecretDialogOpenInjectable;
|
||||
@@ -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 { action } from "mobx";
|
||||
import addSecretDialogOpenStateInjectable from "./state.injectable";
|
||||
|
||||
const openAddSecretDialogInjectable = getInjectable({
|
||||
id: "open-add-secret-dialog",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(addSecretDialogOpenStateInjectable);
|
||||
|
||||
return action(() => state.set(true));
|
||||
},
|
||||
});
|
||||
|
||||
export default openAddSecretDialogInjectable;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 { observable } from "mobx";
|
||||
|
||||
const addSecretDialogOpenStateInjectable = getInjectable({
|
||||
id: "add-secret-dialog-state",
|
||||
instantiate: () => observable.box(false),
|
||||
});
|
||||
|
||||
export default addSecretDialogOpenStateInjectable;
|
||||
File renamed without changes.
+49
-34
@@ -3,26 +3,34 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import "./add-secret-dialog.scss";
|
||||
import "./view.scss";
|
||||
|
||||
import React from "react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { DialogProps } from "../dialog";
|
||||
import { Dialog } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
import { Input } from "../input";
|
||||
import { systemName } from "../input/input_validators";
|
||||
import { reverseSecretTypeMap, secretApi, SecretType } from "../../../common/k8s-api/endpoints";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { NamespaceSelect } from "../+namespaces/namespace-select";
|
||||
import { Select } from "../select";
|
||||
import { Icon } from "../icon";
|
||||
import { base64, iter } from "../../utils";
|
||||
import { Notifications } from "../notifications";
|
||||
import type { DialogProps } from "../../dialog";
|
||||
import { Dialog } from "../../dialog";
|
||||
import { Wizard, WizardStep } from "../../wizard";
|
||||
import { Input } from "../../input";
|
||||
import { systemName } from "../../input/input_validators";
|
||||
import type { SecretApi } from "../../../../common/k8s-api/endpoints";
|
||||
import { reverseSecretTypeMap, SecretType } from "../../../../common/k8s-api/endpoints";
|
||||
import { SubTitle } from "../../layout/sub-title";
|
||||
import { NamespaceSelect } from "../../+namespaces/namespace-select";
|
||||
import { Select } from "../../select";
|
||||
import { Icon } from "../../icon";
|
||||
import { base64, iter } from "../../../utils";
|
||||
import upperFirst from "lodash/upperFirst";
|
||||
import { showDetails } from "../kube-detail-params";
|
||||
import { fromEntries } from "../../../common/utils/objects";
|
||||
import { fromEntries } from "../../../../common/utils/objects";
|
||||
import type { ShowDetails } from "../../kube-detail-params/show-details.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import closeAddSecretDialogInjectable from "./close.injectable";
|
||||
import secretApiInjectable from "../../../../common/k8s-api/endpoints/secret.api.injectable";
|
||||
import showDetailsInjectable from "../../kube-detail-params/show-details.injectable";
|
||||
import isAddSecretDialogOpenInjectable from "./is-open.injectable";
|
||||
import type { ShowCheckedErrorNotification } from "../../notifications/show-checked-error.injectable";
|
||||
import showCheckedErrorNotificationInjectable from "../../notifications/show-checked-error.injectable";
|
||||
|
||||
export interface AddSecretDialogProps extends Partial<DialogProps> {
|
||||
}
|
||||
@@ -42,25 +50,21 @@ interface SecretTemplate {
|
||||
|
||||
type ISecretField = keyof SecretTemplate;
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
});
|
||||
interface Dependencies {
|
||||
secretApi: SecretApi;
|
||||
isAddSecretDialogOpen: IComputedValue<boolean>;
|
||||
closeAddSecretDialog: () => void;
|
||||
showDetails: ShowDetails;
|
||||
showCheckedErrorNotification: ShowCheckedErrorNotification;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
constructor(props: AddSecretDialogProps) {
|
||||
class NonInjectedAddSecretDialog extends React.Component<AddSecretDialogProps & Dependencies> {
|
||||
constructor(props: AddSecretDialogProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
dialogState.isOpen = true;
|
||||
}
|
||||
|
||||
static close() {
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
private secretTemplate: Partial<Record<SecretType, SecretTemplate>> = {
|
||||
[SecretType.Opaque]: {},
|
||||
[SecretType.ServiceAccountToken]: {
|
||||
@@ -82,7 +86,7 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
};
|
||||
|
||||
close = () => {
|
||||
AddSecretDialog.close();
|
||||
this.props.closeAddSecretDialog();
|
||||
};
|
||||
|
||||
private getDataFromFields = (fields: SecretTemplateField[] = [], processValue: (val: string) => string = (val => val)) => {
|
||||
@@ -100,7 +104,7 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
const { data = [], labels = [], annotations = [] } = this.secret[type] ?? {};
|
||||
|
||||
try {
|
||||
const newSecret = await secretApi.create({ namespace, name }, {
|
||||
const newSecret = await this.props.secretApi.create({ namespace, name }, {
|
||||
type,
|
||||
data: this.getDataFromFields(data, val => val ? base64.encode(val) : ""),
|
||||
metadata: {
|
||||
@@ -111,10 +115,10 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
},
|
||||
});
|
||||
|
||||
showDetails(newSecret?.selfLink);
|
||||
this.props.showDetails(newSecret?.selfLink);
|
||||
this.close();
|
||||
} catch (err) {
|
||||
Notifications.checkedError(err, "Unknown error occured while creating a Secret");
|
||||
this.props.showCheckedErrorNotification(err, "Unknown error occured while creating a Secret");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,7 +187,7 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { ...dialogProps } = this.props;
|
||||
const { closeAddSecretDialog, isAddSecretDialogOpen, secretApi, showDetails, ...dialogProps } = this.props;
|
||||
const { namespace, name, type } = this;
|
||||
const header = <h5>Create Secret</h5>;
|
||||
|
||||
@@ -191,7 +195,7 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddSecretDialog"
|
||||
isOpen={dialogState.isOpen}
|
||||
isOpen={isAddSecretDialogOpen.get()}
|
||||
onOpen={this.reset}
|
||||
close={this.close}
|
||||
>
|
||||
@@ -244,3 +248,14 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const AddSecretDialog = withInjectables<Dependencies, AddSecretDialogProps>(NonInjectedAddSecretDialog, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
closeAddSecretDialog: di.inject(closeAddSecretDialogInjectable),
|
||||
secretApi: di.inject(secretApiInjectable),
|
||||
showDetails: di.inject(showDetailsInjectable),
|
||||
isAddSecretDialogOpen: di.inject(isAddSecretDialogOpenInjectable),
|
||||
showCheckedErrorNotification: di.inject(showCheckedErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -7,7 +7,7 @@ import "./secrets.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { AddSecretDialog } from "./add-secret-dialog";
|
||||
import { AddSecretDialog } from "./add-dialog/view";
|
||||
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||
import { Badge } from "../badge";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
@@ -19,6 +19,7 @@ import type { SecretStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import filterByNamespaceInjectable from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
import secretStoreInjectable from "./store.injectable";
|
||||
import openAddSecretDialogInjectable from "./add-dialog/open.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@@ -32,6 +33,7 @@ enum columnId {
|
||||
interface Dependencies {
|
||||
filterByNamespace: FilterByNamespace;
|
||||
secretStore: SecretStore;
|
||||
openAddSecretDialog: () => void;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -89,7 +91,7 @@ class NonInjectedSecrets extends React.Component<Dependencies> {
|
||||
<KubeObjectAge key="age" object={secret} />,
|
||||
]}
|
||||
addRemoveButtons={{
|
||||
onAdd: () => AddSecretDialog.open(),
|
||||
onAdd: this.props.openAddSecretDialog,
|
||||
addTooltip: "Create new Secret",
|
||||
}}
|
||||
/>
|
||||
@@ -104,5 +106,6 @@ export const Secrets = withInjectables<Dependencies>(NonInjectedSecrets, {
|
||||
...props,
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
secretStore: di.inject(secretStoreInjectable),
|
||||
openAddSecretDialog: di.inject(openAddSecretDialogInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import secretApiInjectable from "../../../common/k8s-api/endpoints/secret.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { SecretStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const secretStoreInjectable = getInjectable({
|
||||
|
||||
return new SecretStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -15,13 +15,19 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { Input } from "../input";
|
||||
import { MonacoEditor } from "../monaco-editor";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface CRDDetailsProps extends KubeObjectDetailsProps<CustomResourceDefinition> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class CRDDetails extends React.Component<CRDDetailsProps> {
|
||||
class NonInjectedCRDDetails extends React.Component<CRDDetailsProps & Dependencies> {
|
||||
render() {
|
||||
const { object: crd } = this.props;
|
||||
|
||||
@@ -30,7 +36,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
||||
}
|
||||
|
||||
if (!(crd instanceof CustomResourceDefinition)) {
|
||||
logger.error("[CRDDetails]: passed object that is not an instanceof CustomResourceDefinition", crd);
|
||||
this.props.logger.error("[CRDDetails]: passed object that is not an instanceof CustomResourceDefinition", crd);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -152,3 +158,10 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const CRDDetails = withInjectables<Dependencies, CRDDetailsProps>(NonInjectedCRDDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -11,12 +11,11 @@ import { observer } from "mobx-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { iter, stopPropagation } from "../../utils";
|
||||
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||
import { customResourceDefinitionStore } from "./legacy-store";
|
||||
import { Select } from "../select";
|
||||
import { Icon } from "../icon";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import { TabLayout } from "../layout/tab-layout-2";
|
||||
import type { PageParam } from "../../navigation";
|
||||
import type { PageParam } from "../../navigation/page-param";
|
||||
import type { CustomResourceDefinitionStore } from "./definition.store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import crdGroupsUrlParamInjectable from "./crd-groups-url-param.injectable";
|
||||
@@ -87,7 +86,7 @@ class NonInjectedCustomResourceDefinitions extends React.Component<Dependencies>
|
||||
isConfigurable
|
||||
tableId="crd"
|
||||
className="CrdList"
|
||||
store={customResourceDefinitionStore}
|
||||
store={this.props.customResourceDefinitionStore}
|
||||
// Don't subscribe the `customResourceDefinitionStore` because <Sidebar> already has and is always mounted
|
||||
subscribeStores={false}
|
||||
items={this.items}
|
||||
|
||||
@@ -17,7 +17,9 @@ import { CustomResourceDefinition } from "../../../common/k8s-api/endpoints/cust
|
||||
import { safeJSONPathValue } from "../../utils/jsonPath";
|
||||
import type { KubeObjectMetadata, KubeObjectStatus } from "../../../common/k8s-api/kube-object";
|
||||
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface CustomResourceDetailsProps extends KubeObjectDetailsProps<KubeObject> {
|
||||
crd?: CustomResourceDefinition;
|
||||
@@ -59,8 +61,12 @@ function convertSpecValue(value: unknown): React.ReactNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class CustomResourceDetails extends React.Component<CustomResourceDetailsProps> {
|
||||
class NonInjectedCustomResourceDetails extends React.Component<CustomResourceDetailsProps & Dependencies> {
|
||||
renderAdditionalColumns(resource: KubeObject, columns: AdditionalPrinterColumnsV1[]) {
|
||||
return columns.map(({ name, jsonPath }) => (
|
||||
<DrawerItem key={name} name={name}>
|
||||
@@ -106,7 +112,7 @@ export class CustomResourceDetails extends React.Component<CustomResourceDetails
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props: { object, crd }} = this;
|
||||
const { props: { object, crd, logger }} = this;
|
||||
|
||||
if (!object || !crd) {
|
||||
return null;
|
||||
@@ -134,3 +140,10 @@ export class CustomResourceDetails extends React.Component<CustomResourceDetails
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const CustomResourceDetails = withInjectables<Dependencies, CustomResourceDetailsProps>(NonInjectedCustomResourceDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import assert from "assert";
|
||||
import autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import customResourceDefinitionApiInjectable from "../../../common/k8s-api/endpoints/custom-resource-definition.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { CustomResourceDefinitionStore } from "./definition.store";
|
||||
@@ -21,6 +22,7 @@ const customResourceDefinitionStoreInjectable = getInjectable({
|
||||
return new CustomResourceDefinitionStore({
|
||||
autoRegistration: di.inject(autoRegistrationEmitterInjectable),
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import customResourceDefinitionStoreInjectable from "./definition.store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(customResourceDefinitionStoreInjectable)` instead
|
||||
*/
|
||||
export const customResourceDefinitionStore = asLegacyGlobalForExtensionApi(customResourceDefinitionStoreInjectable);
|
||||
@@ -14,13 +14,14 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { KubeEvent } from "../../../common/k8s-api/endpoints/events.api";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { DurationAbsoluteTimestamp } from "./duration-absolute";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import { cssNames } from "../../utils";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface EventDetailsProps extends KubeObjectDetailsProps<KubeEvent> {
|
||||
}
|
||||
@@ -28,6 +29,7 @@ export interface EventDetailsProps extends KubeObjectDetailsProps<KubeEvent> {
|
||||
interface Dependencies {
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
apiManager: ApiManager;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
const NonInjectedEventDetails = observer(({
|
||||
@@ -35,6 +37,7 @@ const NonInjectedEventDetails = observer(({
|
||||
getDetailsUrl,
|
||||
object: event,
|
||||
className,
|
||||
logger,
|
||||
}: Dependencies & EventDetailsProps) => {
|
||||
if (!event) {
|
||||
return null;
|
||||
@@ -101,5 +104,6 @@ export const EventDetails = withInjectables<Dependencies, EventDetailsProps>(Non
|
||||
...props,
|
||||
apiManager: di.inject(apiManagerInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -12,12 +12,13 @@ import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { cssNames } from "../../utils";
|
||||
import { LocaleDate } from "../locale-date";
|
||||
import type { EventStore } from "./store";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import eventStoreInjectable from "./store.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface KubeEventDetailsProps {
|
||||
object: KubeObject;
|
||||
@@ -26,6 +27,7 @@ export interface KubeEventDetailsProps {
|
||||
interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
eventStore: EventStore;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -46,7 +48,7 @@ class NonInjectedKubeEventDetails extends React.Component<KubeEventDetailsProps
|
||||
}
|
||||
|
||||
if (!(object instanceof KubeObject)) {
|
||||
logger.error("[KubeEventDetails]: passed object that is not an instanceof KubeObject", object);
|
||||
this.props.logger.error("[KubeEventDetails]: passed object that is not an instanceof KubeObject", object);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -93,6 +95,7 @@ export const KubeEventDetails = withInjectables<Dependencies, KubeEventDetailsPr
|
||||
...props,
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
eventStore: di.inject(eventStoreInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ import "./kube-event-icon.scss";
|
||||
import React from "react";
|
||||
import { Icon } from "../icon";
|
||||
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import { eventStore } from "./legacy-store";
|
||||
import { cssNames } from "../../utils";
|
||||
import type { KubeEvent } from "../../../common/k8s-api/endpoints/events.api";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { EventStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import eventStoreInjectable from "./store.injectable";
|
||||
|
||||
export interface KubeEventIconProps {
|
||||
object: KubeObject;
|
||||
@@ -19,22 +21,23 @@ export interface KubeEventIconProps {
|
||||
filterEvents?: (events: KubeEvent[]) => KubeEvent[];
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
eventStore: EventStore;
|
||||
}
|
||||
|
||||
const defaultProps: Partial<KubeEventIconProps> = {
|
||||
showWarningsOnly: true,
|
||||
};
|
||||
|
||||
export class KubeEventIcon extends React.Component<KubeEventIconProps> {
|
||||
static defaultProps = defaultProps as object;
|
||||
class NonInjectedKubeEventIcon extends React.Component<KubeEventIconProps & Dependencies> {
|
||||
get showWarningsOnly() {
|
||||
return this.props.showWarningsOnly ?? true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { object, showWarningsOnly, filterEvents } = this.props;
|
||||
const { object, filterEvents, eventStore } = this.props;
|
||||
const events = eventStore.getEventsByObject(object);
|
||||
let warnings = events.filter(evt => evt.isWarning());
|
||||
|
||||
if (filterEvents) warnings = filterEvents(warnings);
|
||||
|
||||
if (!events.length || (showWarningsOnly && !warnings.length)) {
|
||||
if (!events.length || (this.showWarningsOnly && !warnings.length)) {
|
||||
return null;
|
||||
}
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
@@ -58,3 +61,10 @@ export class KubeEventIcon extends React.Component<KubeEventIconProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const KubeEventIcon = withInjectables<Dependencies, KubeEventIconProps>(NonInjectedKubeEventIcon, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
eventStore: di.inject(eventStoreInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import eventStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(eventStoreInjectable)` instead
|
||||
*/
|
||||
export const eventStore = asLegacyGlobalForExtensionApi(eventStoreInjectable);
|
||||
@@ -7,6 +7,7 @@ import assert from "assert";
|
||||
import getPodByIdInjectable from "../+workloads-pods/get-pod-by-id.injectable";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import kubeEventApiInjectable from "../../../common/k8s-api/endpoints/events.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { EventStore } from "./store";
|
||||
@@ -21,6 +22,7 @@ const eventStoreInjectable = getInjectable({
|
||||
return new EventStore({
|
||||
getPodById: di.inject(getPodByIdInjectable),
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import extensionLoaderInjectable from "../../../../extensions/extension-loader/extension-loader.injectable";
|
||||
import uninstallExtensionInjectable from "../uninstall-extension/uninstall-extension.injectable";
|
||||
import uninstallExtensionInjectable from "../uninstall-extension.injectable";
|
||||
import type { UnpackExtension } from "./unpack-extension.injectable";
|
||||
import unpackExtensionInjectable from "./unpack-extension.injectable";
|
||||
import type { GetExtensionDestFolder } from "./get-extension-dest-folder.injectable";
|
||||
@@ -14,7 +14,7 @@ import createTempFilesAndValidateInjectable from "./create-temp-files-and-valida
|
||||
import extensionInstallationStateStoreInjectable from "../../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import type { Disposer } from "../../../../common/utils";
|
||||
import { disposer } from "../../../../common/utils";
|
||||
import { Notifications } from "../../notifications";
|
||||
import type { ShowNotification } from "../../notifications";
|
||||
import { Button } from "../../button";
|
||||
import type { ExtensionLoader } from "../../../../extensions/extension-loader";
|
||||
import type { LensExtensionId } from "../../../../extensions/lens-extension";
|
||||
@@ -23,6 +23,8 @@ import { remove as removeDir } from "fs-extra";
|
||||
import { shell } from "electron";
|
||||
import type { ExtensionInstallationStateStore } from "../../../../extensions/extension-installation-state-store/extension-installation-state-store";
|
||||
import { ExtensionInstallationState } from "../../../../extensions/extension-installation-state-store/extension-installation-state-store";
|
||||
import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable";
|
||||
import showInfoNotificationInjectable from "../../notifications/show-info-notification.injectable";
|
||||
|
||||
export interface InstallRequest {
|
||||
fileName: string;
|
||||
@@ -36,6 +38,8 @@ interface Dependencies {
|
||||
createTempFilesAndValidate: CreateTempFilesAndValidate;
|
||||
getExtensionDestFolder: GetExtensionDestFolder;
|
||||
installStateStore: ExtensionInstallationStateStore;
|
||||
showErrorNotification: ShowNotification;
|
||||
showInfoNotification: ShowNotification;
|
||||
}
|
||||
|
||||
export type AttemptInstall = (request: InstallRequest, cleanup?: Disposer) => Promise<void>;
|
||||
@@ -47,6 +51,8 @@ const attemptInstall = ({
|
||||
createTempFilesAndValidate,
|
||||
getExtensionDestFolder,
|
||||
installStateStore,
|
||||
showErrorNotification,
|
||||
showInfoNotification,
|
||||
}: Dependencies): AttemptInstall =>
|
||||
async (request, cleanup) => {
|
||||
const dispose = disposer(
|
||||
@@ -66,7 +72,7 @@ const attemptInstall = ({
|
||||
if (curState !== ExtensionInstallationState.IDLE) {
|
||||
dispose();
|
||||
|
||||
return void Notifications.error(
|
||||
return void showErrorNotification(
|
||||
<div className="flex column gaps">
|
||||
<b>Extension Install Collision:</b>
|
||||
<p>
|
||||
@@ -86,7 +92,7 @@ const attemptInstall = ({
|
||||
const { version: oldVersion } = installedExtension.manifest;
|
||||
|
||||
// confirm to uninstall old version before installing new version
|
||||
const removeNotification = Notifications.info(
|
||||
const removeNotification = showInfoNotification(
|
||||
<div className="InstallingExtensionNotification flex gaps align-center">
|
||||
<div className="flex column gaps">
|
||||
<p>
|
||||
@@ -142,6 +148,8 @@ const attemptInstallInjectable = getInjectable({
|
||||
createTempFilesAndValidate: di.inject(createTempFilesAndValidateInjectable),
|
||||
getExtensionDestFolder: di.inject(getExtensionDestFolderInjectable),
|
||||
installStateStore: di.inject(extensionInstallationStateStoreInjectable),
|
||||
showErrorNotification: di.inject(showErrorNotificationInjectable),
|
||||
showInfoNotification: di.inject(showInfoNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { LensExtensionId } from "../../../extensions/lens-extension";
|
||||
import { extensionDisplayName } from "../../../extensions/lens-extension";
|
||||
import type { Confirm } from "../confirm-dialog/confirm.injectable";
|
||||
import confirmInjectable from "../confirm-dialog/confirm.injectable";
|
||||
import uninstallExtensionInjectable from "./uninstall-extension/uninstall-extension.injectable";
|
||||
import uninstallExtensionInjectable from "./uninstall-extension.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
uninstallExtension: (id: LensExtensionId) => Promise<boolean>;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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 extensionLoaderInjectable from "../../../extensions/extension-loader/extension-loader.injectable";
|
||||
import extensionInstallationStateStoreInjectable from "../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import extensionDiscoveryInjectable from "../../../extensions/extension-discovery/extension-discovery.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { LensExtensionId } from "../../../extensions/lens-extension";
|
||||
import { extensionDisplayName } from "../../../extensions/lens-extension";
|
||||
import React from "react";
|
||||
import { when } from "mobx";
|
||||
import { getMessageFromError } from "./get-message-from-error/get-message-from-error";
|
||||
import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable";
|
||||
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
|
||||
|
||||
const uninstallExtensionInjectable = getInjectable({
|
||||
id: "uninstall-extension",
|
||||
|
||||
instantiate: (di) => {
|
||||
const extensionLoader = di.inject(extensionLoaderInjectable);
|
||||
const extensionDiscovery = di.inject(extensionDiscoveryInjectable);
|
||||
const extensionInstallationStateStore = di.inject(extensionInstallationStateStoreInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const showSuccessNotification = di.inject(showSuccessNotificationInjectable);
|
||||
const showErrorNotification = di.inject(showErrorNotificationInjectable);
|
||||
|
||||
return async (extensionId: LensExtensionId): Promise<boolean> => {
|
||||
const ext = extensionLoader.getExtension(extensionId);
|
||||
|
||||
if (!ext) {
|
||||
logger.debug(`[EXTENSIONS]: cannot uninstall ${extensionId}, was not installed`);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const { manifest } = ext;
|
||||
const displayName = extensionDisplayName(manifest.name, manifest.version);
|
||||
|
||||
try {
|
||||
logger.debug(`[EXTENSIONS]: trying to uninstall ${extensionId}`);
|
||||
extensionInstallationStateStore.setUninstalling(extensionId);
|
||||
|
||||
await extensionDiscovery.uninstallExtension(extensionId);
|
||||
|
||||
// wait for the ExtensionLoader to actually uninstall the extension
|
||||
await when(() => !extensionLoader.userExtensions.has(extensionId));
|
||||
|
||||
showSuccessNotification(
|
||||
<p>
|
||||
{"Extension "}
|
||||
<b>{displayName}</b>
|
||||
{" successfully uninstalled!"}
|
||||
</p>,
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
const message = getMessageFromError(error);
|
||||
|
||||
logger.info(
|
||||
`[EXTENSION-UNINSTALL]: uninstalling ${displayName} has failed: ${error}`,
|
||||
{ error },
|
||||
);
|
||||
showErrorNotification(
|
||||
<p>
|
||||
{"Uninstalling extension "}
|
||||
<b>{displayName}</b>
|
||||
{" has failed: "}
|
||||
<em>{message}</em>
|
||||
</p>,
|
||||
);
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
// Remove uninstall state on uninstall failure
|
||||
extensionInstallationStateStore.clearUninstalling(extensionId);
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default uninstallExtensionInjectable;
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* 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 extensionLoaderInjectable from "../../../../extensions/extension-loader/extension-loader.injectable";
|
||||
import { uninstallExtension } from "./uninstall-extension";
|
||||
import extensionInstallationStateStoreInjectable
|
||||
from "../../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import extensionDiscoveryInjectable
|
||||
from "../../../../extensions/extension-discovery/extension-discovery.injectable";
|
||||
|
||||
const uninstallExtensionInjectable = getInjectable({
|
||||
id: "uninstall-extension",
|
||||
|
||||
instantiate: (di) =>
|
||||
uninstallExtension({
|
||||
extensionLoader: di.inject(extensionLoaderInjectable),
|
||||
extensionDiscovery: di.inject(extensionDiscoveryInjectable),
|
||||
extensionInstallationStateStore: di.inject(extensionInstallationStateStoreInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
export default uninstallExtensionInjectable;
|
||||
@@ -1,79 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ExtensionLoader } from "../../../../extensions/extension-loader";
|
||||
import type { LensExtensionId } from "../../../../extensions/lens-extension";
|
||||
import { extensionDisplayName } from "../../../../extensions/lens-extension";
|
||||
import logger from "../../../../main/logger";
|
||||
import type { ExtensionDiscovery } from "../../../../extensions/extension-discovery/extension-discovery";
|
||||
import { Notifications } from "../../notifications";
|
||||
import React from "react";
|
||||
import { when } from "mobx";
|
||||
import { getMessageFromError } from "../get-message-from-error/get-message-from-error";
|
||||
import type { ExtensionInstallationStateStore } from "../../../../extensions/extension-installation-state-store/extension-installation-state-store";
|
||||
|
||||
interface Dependencies {
|
||||
extensionLoader: ExtensionLoader;
|
||||
extensionDiscovery: ExtensionDiscovery;
|
||||
extensionInstallationStateStore: ExtensionInstallationStateStore;
|
||||
}
|
||||
|
||||
export const uninstallExtension = ({
|
||||
extensionLoader,
|
||||
extensionDiscovery,
|
||||
extensionInstallationStateStore,
|
||||
}: Dependencies) => (
|
||||
async (extensionId: LensExtensionId): Promise<boolean> => {
|
||||
const ext = extensionLoader.getExtension(extensionId);
|
||||
|
||||
if (!ext) {
|
||||
logger.debug(`[EXTENSIONS]: cannot uninstall ${extensionId}, was not installed`);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const { manifest } = ext;
|
||||
const displayName = extensionDisplayName(manifest.name, manifest.version);
|
||||
|
||||
try {
|
||||
logger.debug(`[EXTENSIONS]: trying to uninstall ${extensionId}`);
|
||||
extensionInstallationStateStore.setUninstalling(extensionId);
|
||||
|
||||
await extensionDiscovery.uninstallExtension(extensionId);
|
||||
|
||||
// wait for the ExtensionLoader to actually uninstall the extension
|
||||
await when(() => !extensionLoader.userExtensions.has(extensionId));
|
||||
|
||||
Notifications.ok(
|
||||
<p>
|
||||
{"Extension "}
|
||||
<b>{displayName}</b>
|
||||
{" successfully uninstalled!"}
|
||||
</p>,
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
const message = getMessageFromError(error);
|
||||
|
||||
logger.info(
|
||||
`[EXTENSION-UNINSTALL]: uninstalling ${displayName} has failed: ${error}`,
|
||||
{ error },
|
||||
);
|
||||
Notifications.error(
|
||||
<p>
|
||||
{"Uninstalling extension "}
|
||||
<b>{displayName}</b>
|
||||
{" has failed: "}
|
||||
<em>{message}</em>
|
||||
</p>,
|
||||
);
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
// Remove uninstall state on uninstall failure
|
||||
extensionInstallationStateStore.clearUninstalling(extensionId);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -14,7 +14,6 @@ import { Dialog } from "../../dialog";
|
||||
import { Wizard, WizardStep } from "../../wizard";
|
||||
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { Select } from "../../select";
|
||||
import { Notifications } from "../../notifications";
|
||||
import orderBy from "lodash/orderBy";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import releaseRollbackDialogStateInjectable from "./state.injectable";
|
||||
@@ -22,6 +21,8 @@ import type { RollbackRelease } from "../rollback-release/rollback-release.injec
|
||||
import rollbackReleaseInjectable from "../rollback-release/rollback-release.injectable";
|
||||
import type { HelmReleaseRevision, RequestHelmReleaseHistory } from "../../../../common/k8s-api/endpoints/helm-releases.api/request-history.injectable";
|
||||
import requestHelmReleaseHistoryInjectable from "../../../../common/k8s-api/endpoints/helm-releases.api/request-history.injectable";
|
||||
import type { ShowCheckedErrorNotification } from "../../notifications/show-checked-error.injectable";
|
||||
import showCheckedErrorNotificationInjectable from "../../notifications/show-checked-error.injectable";
|
||||
|
||||
export interface ReleaseRollbackDialogProps extends DialogProps {
|
||||
}
|
||||
@@ -30,6 +31,7 @@ interface Dependencies {
|
||||
rollbackRelease: RollbackRelease;
|
||||
state: IObservableValue<HelmRelease | undefined>;
|
||||
requestHelmReleaseHistory: RequestHelmReleaseHistory;
|
||||
showCheckedErrorNotification: ShowCheckedErrorNotification;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -71,7 +73,7 @@ class NonInjectedReleaseRollbackDialog extends React.Component<ReleaseRollbackDi
|
||||
await this.props.rollbackRelease(release.getName(), release.getNs(), revision.revision);
|
||||
this.close();
|
||||
} catch (err) {
|
||||
Notifications.checkedError(err, "Unknown error occured while rolling back release");
|
||||
this.props.showCheckedErrorNotification(err, "Unknown error occured while rolling back release");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,5 +145,6 @@ export const ReleaseRollbackDialog = withInjectables<Dependencies, ReleaseRollba
|
||||
rollbackRelease: di.inject(rollbackReleaseInjectable),
|
||||
state: di.inject(releaseRollbackDialogStateInjectable),
|
||||
requestHelmReleaseHistory: di.inject(requestHelmReleaseHistoryInjectable),
|
||||
showCheckedErrorNotification: di.inject(showCheckedErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -15,13 +15,14 @@ import { Wizard, WizardStep } from "../../wizard";
|
||||
import type { Namespace } from "../../../../common/k8s-api/endpoints";
|
||||
import { Input } from "../../input";
|
||||
import { systemName } from "../../input/input_validators";
|
||||
import { Notifications } from "../../notifications";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import namespaceStoreInjectable from "../store.injectable";
|
||||
import addNamespaceDialogStateInjectable
|
||||
from "./state.injectable";
|
||||
import type { NamespaceStore } from "../store";
|
||||
import { autoBind } from "../../../utils";
|
||||
import type { ShowCheckedErrorNotification } from "../../notifications/show-checked-error.injectable";
|
||||
import showCheckedErrorNotificationInjectable from "../../notifications/show-checked-error.injectable";
|
||||
|
||||
export interface AddNamespaceDialogProps extends DialogProps {
|
||||
onSuccess?(ns: Namespace): void;
|
||||
@@ -31,6 +32,7 @@ export interface AddNamespaceDialogProps extends DialogProps {
|
||||
interface Dependencies {
|
||||
namespaceStore: NamespaceStore;
|
||||
state: IObservableValue<boolean>;
|
||||
showCheckedErrorNotification: ShowCheckedErrorNotification;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -63,7 +65,7 @@ class NonInjectedAddNamespaceDialog extends React.Component<AddNamespaceDialogPr
|
||||
onSuccess?.(created);
|
||||
this.close();
|
||||
} catch (err) {
|
||||
Notifications.checkedError(err, "Unknown error occured while creating the namespace");
|
||||
this.props.showCheckedErrorNotification(err, "Unknown error occured while creating the namespace");
|
||||
onError?.(err);
|
||||
}
|
||||
}
|
||||
@@ -112,5 +114,6 @@ export const AddNamespaceDialog = withInjectables<Dependencies, AddNamespaceDial
|
||||
...props,
|
||||
namespaceStore: di.inject(namespaceStoreInjectable),
|
||||
state: di.inject(addNamespaceDialogStateInjectable),
|
||||
showCheckedErrorNotification: di.inject(showCheckedErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -55,6 +55,9 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
fetchMock = asyncFn();
|
||||
di.override(fetchInjectable, () => fetchMock);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
@@ -71,9 +74,6 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
|
||||
cleanup = disposer(subscribeStores([namespaceStore]));
|
||||
|
||||
fetchMock = asyncFn();
|
||||
di.override(fetchInjectable, () => fetchMock);
|
||||
|
||||
const render = renderFor(di);
|
||||
|
||||
result = render((
|
||||
|
||||
@@ -29,7 +29,7 @@ interface Dependencies {
|
||||
openAddNamespaceDialog: () => void;
|
||||
}
|
||||
|
||||
export const NonInjectedNamespacesRoute = ({ namespaceStore, openAddNamespaceDialog }: Dependencies) => (
|
||||
const NonInjectedNamespacesRoute = ({ namespaceStore, openAddNamespaceDialog }: Dependencies) => (
|
||||
<TabLayout>
|
||||
<KubeObjectListLayout
|
||||
isConfigurable
|
||||
|
||||
@@ -11,6 +11,7 @@ import assert from "assert";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import clusterConfiguredAccessibleNamespacesInjectable from "../../cluster/accessible-namespaces.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
const namespaceStoreInjectable = getInjectable({
|
||||
id: "namespace-store",
|
||||
@@ -25,6 +26,7 @@ const namespaceStoreInjectable = getInjectable({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
storage: createStorage<string[] | undefined>("selected_namespaces", undefined),
|
||||
clusterConfiguredAccessibleNamespaces: di.inject(clusterConfiguredAccessibleNamespacesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -23,12 +23,7 @@ export class NamespaceStore extends KubeObjectStore<Namespace, NamespaceApi> {
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
private async init() {
|
||||
await this.dependencies.storage.whenReady;
|
||||
|
||||
// initialize allowed namespaces
|
||||
const { allowedNamespaces } = this;
|
||||
const selectedNamespaces = this.dependencies.storage.get(); // raw namespaces, undefined on first load
|
||||
|
||||
|
||||
@@ -11,13 +11,19 @@ import { DrawerTitle } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Endpoints } from "../../../common/k8s-api/endpoints";
|
||||
import { EndpointSubsetList } from "./endpoint-subset-list";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface EndpointsDetailsProps extends KubeObjectDetailsProps<Endpoints> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class EndpointsDetails extends React.Component<EndpointsDetailsProps> {
|
||||
class NonInjectedEndpointsDetails extends React.Component<EndpointsDetailsProps & Dependencies> {
|
||||
render() {
|
||||
const { object: endpoint } = this.props;
|
||||
|
||||
@@ -26,7 +32,7 @@ export class EndpointsDetails extends React.Component<EndpointsDetailsProps> {
|
||||
}
|
||||
|
||||
if (!(endpoint instanceof Endpoints)) {
|
||||
logger.error("[EndpointDetails]: passed object that is not an instanceof Endpoint", endpoint);
|
||||
this.props.logger.error("[EndpointDetails]: passed object that is not an instanceof Endpoint", endpoint);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -47,3 +53,10 @@ export class EndpointsDetails extends React.Component<EndpointsDetailsProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const EndpointsDetails = withInjectables<Dependencies, EndpointsDetailsProps>(NonInjectedEndpointsDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import endpointsApiInjectable from "../../../common/k8s-api/endpoints/endpoint.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { EndpointsStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const endpointsStoreInjectable = getInjectable({
|
||||
|
||||
return new EndpointsStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -4,15 +4,13 @@
|
||||
*/
|
||||
import assert from "assert";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import {
|
||||
kubeObjectStoreInjectionToken,
|
||||
} from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import ingressClassApiInjectable
|
||||
from "../../../common/k8s-api/endpoints/ingress-class.api.injectable";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import ingressClassApiInjectable from "../../../common/k8s-api/endpoints/ingress-class.api.injectable";
|
||||
import { IngressClassStore } from "./ingress-class-store";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable
|
||||
from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
const ingressClassStoreInjectable = getInjectable({
|
||||
id: "ingress-class-store",
|
||||
@@ -23,7 +21,8 @@ const ingressClassStoreInjectable = getInjectable({
|
||||
const api = di.inject(ingressClassApiInjectable);
|
||||
|
||||
return new IngressClassStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import ingressApiInjectable from "../../../common/k8s-api/endpoints/ingress.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { IngressStore } from "./ingress-store";
|
||||
@@ -19,6 +20,7 @@ const ingressStoreInjectable = getInjectable({
|
||||
|
||||
return new IngressStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -13,15 +13,21 @@ import { Badge } from "../badge";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import type { LabelMatchExpression, LabelSelector } from "../../../common/k8s-api/kube-object";
|
||||
import { isEmpty } from "lodash";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface NetworkPolicyDetailsProps extends KubeObjectDetailsProps<NetworkPolicy> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsProps> {
|
||||
class NonInjectedNetworkPolicyDetails extends React.Component<NetworkPolicyDetailsProps & Dependencies> {
|
||||
renderIPolicyIpBlock(ipBlock: IPolicyIpBlock | undefined) {
|
||||
if (!ipBlock) {
|
||||
return null;
|
||||
@@ -159,7 +165,7 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
||||
}
|
||||
|
||||
if (!(policy instanceof NetworkPolicy)) {
|
||||
logger.error("[NetworkPolicyDetails]: passed object that is not an instanceof NetworkPolicy", policy);
|
||||
this.props.logger.error("[NetworkPolicyDetails]: passed object that is not an instanceof NetworkPolicy", policy);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -204,3 +210,10 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const NetworkPolicyDetails = withInjectables<Dependencies, NetworkPolicyDetailsProps>(NonInjectedNetworkPolicyDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import networkPolicyApiInjectable from "../../../common/k8s-api/endpoints/network-policy.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { NetworkPolicyStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const networkPolicyStoreInjectable = getInjectable({
|
||||
|
||||
return new NetworkPolicyStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -11,19 +11,33 @@ import type { PortForwardItem } from "../../port-forward";
|
||||
import { portForwardAddress } from "../../port-forward";
|
||||
import { Drawer, DrawerItem } from "../drawer";
|
||||
import { cssNames } from "../../utils";
|
||||
import { podApi, serviceApi } from "../../../common/k8s-api/endpoints";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import type { PodApi, ServiceApi } from "../../../common/k8s-api/endpoints";
|
||||
import { PortForwardMenu } from "./port-forward-menu";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import serviceApiInjectable from "../../../common/k8s-api/endpoints/service.api.injectable";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import podApiInjectable from "../../../common/k8s-api/endpoints/pod.api.injectable";
|
||||
|
||||
export interface PortForwardDetailsProps {
|
||||
portForward: PortForwardItem;
|
||||
hideDetails(): void;
|
||||
}
|
||||
|
||||
export class PortForwardDetails extends React.Component<PortForwardDetailsProps> {
|
||||
interface Dependencies {
|
||||
serviceApi: ServiceApi;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
podApi: PodApi;
|
||||
}
|
||||
|
||||
class NonInjectedPortForwardDetails extends React.Component<PortForwardDetailsProps & Dependencies> {
|
||||
renderResourceName() {
|
||||
const { portForward } = this.props;
|
||||
const {
|
||||
portForward,
|
||||
serviceApi,
|
||||
podApi,
|
||||
getDetailsUrl,
|
||||
} = this.props;
|
||||
const name = portForward.getName();
|
||||
const api = {
|
||||
"service": serviceApi,
|
||||
@@ -37,7 +51,7 @@ export class PortForwardDetails extends React.Component<PortForwardDetailsProps>
|
||||
}
|
||||
|
||||
return (
|
||||
<Link to={getDetailsUrl(api.getUrl({ name, namespace: portForward.getNs() }))}>
|
||||
<Link to={getDetailsUrl(api.formatUrlForNotListing({ name, namespace: portForward.getNs() }))}>
|
||||
{name}
|
||||
</Link>
|
||||
);
|
||||
@@ -99,3 +113,12 @@ export class PortForwardDetails extends React.Component<PortForwardDetailsProps>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PortForwardDetails = withInjectables<Dependencies, PortForwardDetailsProps>(NonInjectedPortForwardDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
serviceApi: di.inject(serviceApiInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
podApi: di.inject(podApiInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -10,12 +10,13 @@ import type { MenuActionsProps } from "../menu/menu-actions";
|
||||
import { MenuActions } from "../menu/menu-actions";
|
||||
import { MenuItem } from "../menu";
|
||||
import { Icon } from "../icon";
|
||||
import { Notifications } from "../notifications";
|
||||
import type { ShowNotification } from "../notifications";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import portForwardDialogModelInjectable from "../../port-forward/port-forward-dialog-model/port-forward-dialog-model.injectable";
|
||||
import portForwardStoreInjectable from "../../port-forward/port-forward-store/port-forward-store.injectable";
|
||||
import type { OpenPortForward } from "../../port-forward/open-port-forward.injectable";
|
||||
import openPortForwardInjectable from "../../port-forward/open-port-forward.injectable";
|
||||
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
|
||||
|
||||
export interface PortForwardMenuProps extends MenuActionsProps {
|
||||
portForward: PortForwardItem;
|
||||
@@ -26,6 +27,7 @@ interface Dependencies {
|
||||
portForwardStore: PortForwardStore;
|
||||
openPortForwardDialog: (item: PortForwardItem) => void;
|
||||
openPortForward: OpenPortForward;
|
||||
showErrorNotification: ShowNotification;
|
||||
}
|
||||
|
||||
class NonInjectedPortForwardMenu<Props extends PortForwardMenuProps & Dependencies> extends React.Component<Props> {
|
||||
@@ -35,12 +37,12 @@ class NonInjectedPortForwardMenu<Props extends PortForwardMenuProps & Dependenci
|
||||
}
|
||||
|
||||
remove() {
|
||||
const { portForward } = this.props;
|
||||
const { portForward, showErrorNotification } = this.props;
|
||||
|
||||
try {
|
||||
this.portForwardStore.remove(portForward);
|
||||
} catch (error) {
|
||||
Notifications.error(`Error occurred stopping the port-forward from port ${portForward.forwardPort}. The port-forward may still be active.`);
|
||||
showErrorNotification(`Error occurred stopping the port-forward from port ${portForward.forwardPort}. The port-forward may still be active.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +51,14 @@ class NonInjectedPortForwardMenu<Props extends PortForwardMenuProps & Dependenci
|
||||
}
|
||||
|
||||
private startPortForwarding = async () => {
|
||||
const { portForward } = this.props;
|
||||
const { portForward, showErrorNotification } = this.props;
|
||||
|
||||
const pf = await this.portForwardStore.start(portForward);
|
||||
|
||||
if (pf.status === "Disabled") {
|
||||
const { name, kind, forwardPort } = portForward;
|
||||
|
||||
Notifications.error(`Error occurred starting port-forward, the local port ${forwardPort} may not be available or the ${kind} ${name} may not be reachable`);
|
||||
showErrorNotification(`Error occurred starting port-forward, the local port ${forwardPort} may not be available or the ${kind} ${name} may not be reachable`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -134,15 +136,12 @@ class NonInjectedPortForwardMenu<Props extends PortForwardMenuProps & Dependenci
|
||||
}
|
||||
}
|
||||
|
||||
export const PortForwardMenu = withInjectables<Dependencies, PortForwardMenuProps>(
|
||||
NonInjectedPortForwardMenu,
|
||||
|
||||
{
|
||||
getProps: (di, props) => ({
|
||||
portForwardStore: di.inject(portForwardStoreInjectable),
|
||||
openPortForwardDialog: di.inject(portForwardDialogModelInjectable).open,
|
||||
openPortForward: di.inject(openPortForwardInjectable),
|
||||
...props,
|
||||
}),
|
||||
},
|
||||
);
|
||||
export const PortForwardMenu = withInjectables<Dependencies, PortForwardMenuProps>(NonInjectedPortForwardMenu, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
portForwardStore: di.inject(portForwardStoreInjectable),
|
||||
openPortForwardDialog: di.inject(portForwardDialogModelInjectable).open,
|
||||
openPortForward: di.inject(openPortForwardInjectable),
|
||||
showErrorNotification: di.inject(showErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -15,12 +15,13 @@ import { ServicePortComponent } from "./service-port-component";
|
||||
import type { EndpointsStore } from "../+network-endpoints/store";
|
||||
import { ServiceDetailsEndpoint } from "./service-details-endpoint";
|
||||
import type { PortForwardStore } from "../../port-forward";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import portForwardStoreInjectable from "../../port-forward/port-forward-store/port-forward-store.injectable";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import endpointsStoreInjectable from "../+network-endpoints/store.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface ServiceDetailsProps extends KubeObjectDetailsProps<Service> {
|
||||
}
|
||||
@@ -29,6 +30,7 @@ interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
portForwardStore: PortForwardStore;
|
||||
endpointsStore: EndpointsStore;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -59,7 +61,7 @@ class NonInjectedServiceDetails extends React.Component<ServiceDetailsProps & De
|
||||
}
|
||||
|
||||
if (!(service instanceof Service)) {
|
||||
logger.error("[ServiceDetails]: passed object that is not an instanceof Service", service);
|
||||
this.props.logger.error("[ServiceDetails]: passed object that is not an instanceof Service", service);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -155,5 +157,6 @@ export const ServiceDetails = withInjectables<Dependencies, ServiceDetailsProps>
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
portForwardStore: di.inject(portForwardStoreInjectable),
|
||||
endpointsStore: di.inject(endpointsStoreInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { Service, ServicePort } from "../../../common/k8s-api/endpoints";
|
||||
import { action, makeObservable, observable, reaction } from "mobx";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Notifications } from "../notifications";
|
||||
import type { ShowNotification } from "../notifications";
|
||||
import { Button } from "../button";
|
||||
import type { ForwardedPort, PortForwardStore } from "../../port-forward";
|
||||
import { predictProtocol } from "../../port-forward";
|
||||
@@ -18,11 +18,13 @@ import { Spinner } from "../spinner";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import portForwardStoreInjectable from "../../port-forward/port-forward-store/port-forward-store.injectable";
|
||||
import portForwardDialogModelInjectable from "../../port-forward/port-forward-dialog-model/port-forward-dialog-model.injectable";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import aboutPortForwardingInjectable from "../../port-forward/about-port-forwarding.injectable";
|
||||
import notifyErrorPortForwardingInjectable from "../../port-forward/notify-error-port-forwarding.injectable";
|
||||
import type { OpenPortForward } from "../../port-forward/open-port-forward.injectable";
|
||||
import openPortForwardInjectable from "../../port-forward/open-port-forward.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
|
||||
|
||||
export interface ServicePortComponentProps {
|
||||
service: Service;
|
||||
@@ -31,10 +33,12 @@ export interface ServicePortComponentProps {
|
||||
|
||||
interface Dependencies {
|
||||
portForwardStore: PortForwardStore;
|
||||
logger: Logger;
|
||||
openPortForwardDialog: (item: ForwardedPort, options: { openInBrowser: boolean; onClose: () => void }) => void;
|
||||
aboutPortForwarding: () => void;
|
||||
notifyErrorPortForwarding: (message: string) => void;
|
||||
openPortForward: OpenPortForward;
|
||||
showErrorNotification: ShowNotification;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -127,7 +131,7 @@ class NonInjectedServicePortComponent extends React.Component<ServicePortCompone
|
||||
this.props.notifyErrorPortForwarding(`Error occurred starting port-forward, the local port may not be available or the ${portForward.kind} ${portForward.name} may not be reachable`);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("[SERVICE-PORT-COMPONENT]:", error, portForward);
|
||||
this.props.logger.error("[SERVICE-PORT-COMPONENT]:", error, portForward);
|
||||
} finally {
|
||||
this.checkExistingPortForwarding();
|
||||
this.waiting = false;
|
||||
@@ -136,7 +140,7 @@ class NonInjectedServicePortComponent extends React.Component<ServicePortCompone
|
||||
|
||||
@action
|
||||
async stopPortForward() {
|
||||
const { service, port } = this.props;
|
||||
const { service, port, showErrorNotification } = this.props;
|
||||
const portForward: ForwardedPort = {
|
||||
kind: "service",
|
||||
name: service.getName(),
|
||||
@@ -150,7 +154,7 @@ class NonInjectedServicePortComponent extends React.Component<ServicePortCompone
|
||||
try {
|
||||
await this.portForwardStore.remove(portForward);
|
||||
} catch (error) {
|
||||
Notifications.error(`Error occurred stopping the port-forward from port ${portForward.forwardPort}.`);
|
||||
showErrorNotification(`Error occurred stopping the port-forward from port ${portForward.forwardPort}.`);
|
||||
} finally {
|
||||
this.checkExistingPortForwarding();
|
||||
this.forwardPort = 0;
|
||||
@@ -196,18 +200,16 @@ class NonInjectedServicePortComponent extends React.Component<ServicePortCompone
|
||||
}
|
||||
}
|
||||
|
||||
export const ServicePortComponent = withInjectables<Dependencies, ServicePortComponentProps>(
|
||||
NonInjectedServicePortComponent,
|
||||
|
||||
{
|
||||
getProps: (di, props) => ({
|
||||
portForwardStore: di.inject(portForwardStoreInjectable),
|
||||
openPortForwardDialog: di.inject(portForwardDialogModelInjectable).open,
|
||||
aboutPortForwarding: di.inject(aboutPortForwardingInjectable),
|
||||
notifyErrorPortForwarding: di.inject(notifyErrorPortForwardingInjectable),
|
||||
openPortForward: di.inject(openPortForwardInjectable),
|
||||
...props,
|
||||
}),
|
||||
},
|
||||
);
|
||||
export const ServicePortComponent = withInjectables<Dependencies, ServicePortComponentProps>(NonInjectedServicePortComponent, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
portForwardStore: di.inject(portForwardStoreInjectable),
|
||||
openPortForwardDialog: di.inject(portForwardDialogModelInjectable).open,
|
||||
aboutPortForwarding: di.inject(aboutPortForwardingInjectable),
|
||||
notifyErrorPortForwarding: di.inject(notifyErrorPortForwardingInjectable),
|
||||
openPortForward: di.inject(openPortForwardInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
showErrorNotification: di.inject(showErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import serviceApiInjectable from "../../../common/k8s-api/endpoints/service.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { ServiceStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const serviceStoreInjectable = getInjectable({
|
||||
|
||||
return new ServiceStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import nodeApiInjectable from "../../../common/k8s-api/endpoints/node.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { NodeStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const nodeStoreInjectable = getInjectable({
|
||||
|
||||
return new NodeStore({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import podSecurityPolicyStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(podSecurityPolicyStoreInjectable)` instead
|
||||
*/
|
||||
export const podSecurityPolicyStore = asLegacyGlobalForExtensionApi(podSecurityPolicyStoreInjectable);
|
||||
@@ -8,10 +8,12 @@ import "./pod-security-policies.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||
import { podSecurityPolicyStore } from "./legacy-store";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { PodSecurityPolicyStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import podSecurityPolicyStoreInjectable from "./store.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@@ -20,8 +22,12 @@ enum columnId {
|
||||
age = "age",
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
podSecurityPolicyStore: PodSecurityPolicyStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PodSecurityPolicies extends React.Component {
|
||||
class NonInjectedPodSecurityPolicies extends React.Component<Dependencies> {
|
||||
render() {
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@@ -29,7 +35,7 @@ export class PodSecurityPolicies extends React.Component {
|
||||
isConfigurable
|
||||
tableId="access_pod_security_policies"
|
||||
className="PodSecurityPolicies"
|
||||
store={podSecurityPolicyStore}
|
||||
store={this.props.podSecurityPolicyStore}
|
||||
sortingCallbacks={{
|
||||
[columnId.name]: podSecurityPolicy => podSecurityPolicy.getName(),
|
||||
[columnId.volumes]: podSecurityPolicy => podSecurityPolicy.getVolumes(),
|
||||
@@ -61,3 +67,10 @@ export class PodSecurityPolicies extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PodSecurityPolicies = withInjectables<Dependencies>(NonInjectedPodSecurityPolicies, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
podSecurityPolicyStore: di.inject(podSecurityPolicyStoreInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -12,7 +12,9 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { PodSecurityPolicy } from "../../../common/k8s-api/endpoints";
|
||||
import { Badge } from "../badge";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface PodSecurityPolicyDetailsProps extends KubeObjectDetailsProps<PodSecurityPolicy> {
|
||||
}
|
||||
@@ -25,8 +27,12 @@ interface RuleGroup {
|
||||
}[];
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps> {
|
||||
class NonInjectedPodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps & Dependencies> {
|
||||
renderRuleGroup(title: React.ReactNode, group: RuleGroup | undefined) {
|
||||
if (!group) return null;
|
||||
const { rule, ranges } = group;
|
||||
@@ -59,7 +65,7 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
||||
}
|
||||
|
||||
if (!(psp instanceof PodSecurityPolicy)) {
|
||||
logger.error("[PodSecurityPolicyDetails]: passed object that is not an instanceof PodSecurityPolicy", psp);
|
||||
this.props.logger.error("[PodSecurityPolicyDetails]: passed object that is not an instanceof PodSecurityPolicy", psp);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -225,3 +231,10 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PodSecurityPolicyDetails = withInjectables<Dependencies, PodSecurityPolicyDetailsProps>(NonInjectedPodSecurityPolicyDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import podSecurityPolicyApiInjectable from "../../../common/k8s-api/endpoints/pod-security-policy.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { PodSecurityPolicyStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const podSecurityPolicyStoreInjectable = getInjectable({
|
||||
|
||||
return new PodSecurityPolicyStore({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import storageClassStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(storageClassStoreInjectable)` instead
|
||||
*/
|
||||
export const storageClassStore = asLegacyGlobalForExtensionApi(storageClassStoreInjectable);
|
||||
@@ -15,12 +15,13 @@ import { StorageClass } from "../../../common/k8s-api/endpoints";
|
||||
import type { StorageClassStore } from "./store";
|
||||
import { VolumeDetailsList } from "../+storage-volumes/volume-details-list";
|
||||
import type { PersistentVolumeStore } from "../+storage-volumes/store";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import storageClassStoreInjectable from "./store.injectable";
|
||||
import persistentVolumeStoreInjectable from "../+storage-volumes/store.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface StorageClassDetailsProps extends KubeObjectDetailsProps<StorageClass> {
|
||||
}
|
||||
@@ -29,6 +30,7 @@ interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
storageClassStore: StorageClassStore;
|
||||
persistentVolumeStore: PersistentVolumeStore;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -49,7 +51,7 @@ class NonInjectedStorageClassDetails extends React.Component<StorageClassDetails
|
||||
}
|
||||
|
||||
if (!(storageClass instanceof StorageClass)) {
|
||||
logger.error("[StorageClassDetails]: passed object that is not an instanceof StorageClass", storageClass);
|
||||
this.props.logger.error("[StorageClassDetails]: passed object that is not an instanceof StorageClass", storageClass);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -100,6 +102,7 @@ export const StorageClassDetails = withInjectables<Dependencies, StorageClassDet
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
storageClassStore: di.inject(storageClassStoreInjectable),
|
||||
persistentVolumeStore: di.inject(persistentVolumeStoreInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -8,10 +8,12 @@ import "./storage-classes.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||
import { storageClassStore } from "./legacy-store";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { StorageClassStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import storageClassStoreInjectable from "./store.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@@ -21,8 +23,12 @@ enum columnId {
|
||||
reclaimPolicy = "reclaim",
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
storageClassStore: StorageClassStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class StorageClasses extends React.Component {
|
||||
class NonInjectedStorageClasses extends React.Component<Dependencies> {
|
||||
render() {
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@@ -30,7 +36,7 @@ export class StorageClasses extends React.Component {
|
||||
isConfigurable
|
||||
tableId="storage_classes"
|
||||
className="StorageClasses"
|
||||
store={storageClassStore}
|
||||
store={this.props.storageClassStore}
|
||||
sortingCallbacks={{
|
||||
[columnId.name]: storageClass => storageClass.getName(),
|
||||
[columnId.age]: storageClass => -storageClass.getCreationTimestamp(),
|
||||
@@ -63,3 +69,10 @@ export class StorageClasses extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const StorageClasses = withInjectables<Dependencies>(NonInjectedStorageClasses, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
storageClassStore: di.inject(storageClassStoreInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import assert from "assert";
|
||||
import getPersistentVolumesByStorageClassInjectable from "../+storage-volumes/get-persisten-volumes-by-storage-class.injectable";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import storageClassApiInjectable from "../../../common/k8s-api/endpoints/storage-class.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { StorageClassStore } from "./store";
|
||||
@@ -21,6 +22,7 @@ const storageClassStoreInjectable = getInjectable({
|
||||
return new StorageClassStore({
|
||||
getPersistentVolumesByStorageClass: di.inject(getPersistentVolumesByStorageClassInjectable),
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import persistentVolumeClaimApiInjectable from "../../../common/k8s-api/endpoints/persistent-volume-claim.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { PersistentVolumeClaimStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const persistentVolumeClaimStoreInjectable = getInjectable({
|
||||
|
||||
return new PersistentVolumeClaimStore({
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import persistentVolumeStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(persistentVolumeStoreInjectable)` instead
|
||||
*/
|
||||
export const persistentVolumeStore = asLegacyGlobalForExtensionApi(persistentVolumeStoreInjectable);
|
||||
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import persistentVolumeApiInjectable from "../../../common/k8s-api/endpoints/persistent-volume.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import { PersistentVolumeStore } from "./store";
|
||||
@@ -19,6 +20,7 @@ const persistentVolumeStoreInjectable = getInjectable({
|
||||
|
||||
return new PersistentVolumeStore({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -10,14 +10,17 @@ import { observer } from "mobx-react";
|
||||
import type { PersistentVolume } from "../../../common/k8s-api/endpoints/persistent-volume.api";
|
||||
import { TableRow } from "../table/table-row";
|
||||
import { cssNames, prevDefault } from "../../utils";
|
||||
import { showDetails } from "../kube-detail-params";
|
||||
import { TableCell } from "../table/table-cell";
|
||||
import { Spinner } from "../spinner/spinner";
|
||||
import { DrawerTitle } from "../drawer/drawer-title";
|
||||
import { Table } from "../table/table";
|
||||
import { TableHead } from "../table/table-head";
|
||||
import { persistentVolumeStore } from "./legacy-store";
|
||||
import kebabCase from "lodash/kebabCase";
|
||||
import type { PersistentVolumeStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import persistentVolumeStoreInjectable from "./store.injectable";
|
||||
import type { ShowDetails } from "../kube-detail-params/show-details.injectable";
|
||||
import showDetailsInjectable from "../kube-detail-params/show-details.injectable";
|
||||
|
||||
export interface VolumeDetailsListProps {
|
||||
persistentVolumes: PersistentVolume[];
|
||||
@@ -29,8 +32,13 @@ enum sortBy {
|
||||
capacity = "capacity",
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
persistentVolumeStore: PersistentVolumeStore;
|
||||
showDetails: ShowDetails;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class VolumeDetailsList extends React.Component<VolumeDetailsListProps> {
|
||||
class NonInjectedVolumeDetailsList extends React.Component<VolumeDetailsListProps & Dependencies> {
|
||||
private sortingCallbacks = {
|
||||
[sortBy.name]: (volume: PersistentVolume) => volume.getName(),
|
||||
[sortBy.capacity]: (volume: PersistentVolume) => volume.getCapacity(),
|
||||
@@ -38,7 +46,7 @@ export class VolumeDetailsList extends React.Component<VolumeDetailsListProps> {
|
||||
};
|
||||
|
||||
getTableRow = (uid: string) => {
|
||||
const { persistentVolumes } = this.props;
|
||||
const { persistentVolumes, showDetails } = this.props;
|
||||
const volume = persistentVolumes.find(volume => volume.getId() === uid);
|
||||
|
||||
if (!volume) {
|
||||
@@ -60,7 +68,7 @@ export class VolumeDetailsList extends React.Component<VolumeDetailsListProps> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { persistentVolumes } = this.props;
|
||||
const { persistentVolumes, persistentVolumeStore } = this.props;
|
||||
const virtual = persistentVolumes.length > 100;
|
||||
|
||||
if (!persistentVolumes.length) {
|
||||
@@ -94,3 +102,11 @@ export class VolumeDetailsList extends React.Component<VolumeDetailsListProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const VolumeDetailsList = withInjectables<Dependencies, VolumeDetailsListProps>(NonInjectedVolumeDetailsList, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
persistentVolumeStore: di.inject(persistentVolumeStoreInjectable),
|
||||
showDetails: di.inject(showDetailsInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -11,19 +11,38 @@ import { Link } from "react-router-dom";
|
||||
import { observer } from "mobx-react";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { PersistentVolume, persistentVolumeClaimApi, storageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import type { PersistentVolumeClaimApi, StorageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import { PersistentVolume } from "../../../common/k8s-api/endpoints";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { stopPropagation } from "../../../renderer/utils";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import persistentVolumeClaimApiInjectable from "../../../common/k8s-api/endpoints/persistent-volume-claim.api.injectable";
|
||||
import storageClassApiInjectable from "../../../common/k8s-api/endpoints/storage-class.api.injectable";
|
||||
|
||||
export interface PersistentVolumeDetailsProps extends KubeObjectDetailsProps<PersistentVolume> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
logger: Logger;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
storageClassApi: StorageClassApi;
|
||||
persistentVolumeClaimApi: PersistentVolumeClaimApi;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PersistentVolumeDetails extends React.Component<PersistentVolumeDetailsProps> {
|
||||
class NonInjectedPersistentVolumeDetails extends React.Component<PersistentVolumeDetailsProps & Dependencies> {
|
||||
render() {
|
||||
const { object: volume } = this.props;
|
||||
const {
|
||||
object: volume,
|
||||
storageClassApi,
|
||||
getDetailsUrl,
|
||||
logger,
|
||||
persistentVolumeClaimApi,
|
||||
} = this.props;
|
||||
|
||||
if (!volume) {
|
||||
return null;
|
||||
@@ -37,7 +56,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
||||
|
||||
const { accessModes, capacity, persistentVolumeReclaimPolicy, storageClassName, claimRef, flexVolume, mountOptions, nfs } = volume.spec;
|
||||
|
||||
const storageClassDetailsUrl = getDetailsUrl(storageClassApi.getUrl({
|
||||
const storageClassDetailsUrl = getDetailsUrl(storageClassApi.formatUrlForNotListing({
|
||||
name: storageClassName,
|
||||
}));
|
||||
|
||||
@@ -108,7 +127,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
||||
{claimRef.kind}
|
||||
</DrawerItem>
|
||||
<DrawerItem name="Name">
|
||||
<Link to={getDetailsUrl(persistentVolumeClaimApi.getUrl(claimRef))}>
|
||||
<Link to={getDetailsUrl(persistentVolumeClaimApi.formatUrlForNotListing(claimRef))}>
|
||||
{claimRef.name}
|
||||
</Link>
|
||||
</DrawerItem>
|
||||
@@ -121,3 +140,13 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PersistentVolumeDetails = withInjectables<Dependencies, PersistentVolumeDetailsProps>(NonInjectedPersistentVolumeDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
logger: di.inject(loggerInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
persistentVolumeClaimApi: di.inject(persistentVolumeClaimApiInjectable),
|
||||
storageClassApi: di.inject(storageClassApiInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -9,13 +9,18 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import { stopPropagation } from "../../utils";
|
||||
import { persistentVolumeStore } from "./legacy-store";
|
||||
import { persistentVolumeClaimApi, storageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import type { PersistentVolumeClaimApi, StorageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { PersistentVolumeStore } from "./store";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import persistentVolumeClaimApiInjectable from "../../../common/k8s-api/endpoints/persistent-volume-claim.api.injectable";
|
||||
import persistentVolumeStoreInjectable from "./store.injectable";
|
||||
import storageClassApiInjectable from "../../../common/k8s-api/endpoints/storage-class.api.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@@ -26,9 +31,23 @@ enum columnId {
|
||||
age = "age",
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
storageClassApi: StorageClassApi;
|
||||
persistentVolumeStore: PersistentVolumeStore;
|
||||
persistentVolumeClaimApi: PersistentVolumeClaimApi;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PersistentVolumes extends React.Component {
|
||||
class NonInjectedPersistentVolumes extends React.Component<Dependencies> {
|
||||
render() {
|
||||
const {
|
||||
getDetailsUrl,
|
||||
persistentVolumeStore,
|
||||
storageClassApi,
|
||||
persistentVolumeClaimApi,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
<KubeObjectListLayout
|
||||
@@ -59,7 +78,7 @@ export class PersistentVolumes extends React.Component {
|
||||
]}
|
||||
renderTableContents={volume => {
|
||||
const { claimRef, storageClassName } = volume.spec;
|
||||
const storageClassDetailsUrl = getDetailsUrl(storageClassApi.getUrl({
|
||||
const storageClassDetailsUrl = getDetailsUrl(storageClassApi.formatUrlForNotListing({
|
||||
name: storageClassName,
|
||||
}));
|
||||
|
||||
@@ -75,7 +94,7 @@ export class PersistentVolumes extends React.Component {
|
||||
</Link>,
|
||||
volume.getCapacity(),
|
||||
claimRef && (
|
||||
<Link to={getDetailsUrl(persistentVolumeClaimApi.getUrl(claimRef))} onClick={stopPropagation}>
|
||||
<Link to={getDetailsUrl(persistentVolumeClaimApi.formatUrlForNotListing(claimRef))} onClick={stopPropagation}>
|
||||
{claimRef.name}
|
||||
</Link>
|
||||
),
|
||||
@@ -88,3 +107,13 @@ export class PersistentVolumes extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PersistentVolumes = withInjectables<Dependencies>(NonInjectedPersistentVolumes, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
persistentVolumeClaimApi: di.inject(persistentVolumeClaimApiInjectable),
|
||||
persistentVolumeStore: di.inject(persistentVolumeStoreInjectable),
|
||||
storageClassApi: di.inject(storageClassApiInjectable),
|
||||
}),
|
||||
});
|
||||
+12
-3
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { ClusterRoleBindingDialog } from "../dialog";
|
||||
import { ClusterRoleBindingDialog } from "../dialog/view";
|
||||
import { ClusterRole } from "../../../../../common/k8s-api/endpoints";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
||||
@@ -16,9 +16,15 @@ import directoryForUserDataInjectable from "../../../../../common/app-paths/dire
|
||||
import directoryForKubeConfigsInjectable from "../../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import hostedClusterInjectable from "../../../../cluster-frame-context/hosted-cluster.injectable";
|
||||
import createClusterInjectable from "../../../../cluster/create-cluster.injectable";
|
||||
import type { CloseClusterRoleBindingDialog } from "../dialog/close.injectable";
|
||||
import closeClusterRoleBindingDialogInjectable from "../dialog/close.injectable";
|
||||
import type { OpenClusterRoleBindingDialog } from "../dialog/open.injectable";
|
||||
import openClusterRoleBindingDialogInjectable from "../dialog/open.injectable";
|
||||
|
||||
describe("ClusterRoleBindingDialog tests", () => {
|
||||
let render: DiRender;
|
||||
let closeClusterRoleBindingDialog: CloseClusterRoleBindingDialog;
|
||||
let openClusterRoleBindingDialog: OpenClusterRoleBindingDialog;
|
||||
|
||||
beforeEach(() => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
@@ -27,6 +33,9 @@ describe("ClusterRoleBindingDialog tests", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
closeClusterRoleBindingDialog = di.inject(closeClusterRoleBindingDialogInjectable);
|
||||
openClusterRoleBindingDialog = di.inject(openClusterRoleBindingDialogInjectable);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
@@ -56,7 +65,7 @@ describe("ClusterRoleBindingDialog tests", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
ClusterRoleBindingDialog.close();
|
||||
closeClusterRoleBindingDialog();
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
@@ -67,7 +76,7 @@ describe("ClusterRoleBindingDialog tests", () => {
|
||||
});
|
||||
|
||||
it("clusterrole select should be searchable", async () => {
|
||||
ClusterRoleBindingDialog.open();
|
||||
openClusterRoleBindingDialog();
|
||||
const res = render(<ClusterRoleBindingDialog />);
|
||||
|
||||
userEvent.keyboard("a");
|
||||
|
||||
@@ -15,18 +15,22 @@ import { AddRemoveButtons } from "../../add-remove-buttons";
|
||||
import { DrawerTitle } from "../../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../../table";
|
||||
import { ClusterRoleBindingDialog } from "./dialog";
|
||||
import { clusterRoleBindingStore } from "./legacy-store";
|
||||
import { hashSubject } from "../hashers";
|
||||
import type { OpenConfirmDialog } from "../../confirm-dialog/open.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import openConfirmDialogInjectable from "../../confirm-dialog/open.injectable";
|
||||
import type { ClusterRoleBindingStore } from "./store";
|
||||
import type { OpenClusterRoleBindingDialog } from "./dialog/open.injectable";
|
||||
import openClusterRoleBindingDialogInjectable from "./dialog/open.injectable";
|
||||
import clusterRoleBindingStoreInjectable from "./store.injectable";
|
||||
|
||||
export interface ClusterRoleBindingDetailsProps extends KubeObjectDetailsProps<ClusterRoleBinding> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
openConfirmDialog: OpenConfirmDialog;
|
||||
openClusterRoleBindingDialog: OpenClusterRoleBindingDialog;
|
||||
clusterRoleBindingStore: ClusterRoleBindingStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -47,7 +51,7 @@ class NonInjectedClusterRoleBindingDetails extends React.Component<ClusterRoleBi
|
||||
}
|
||||
|
||||
removeSelectedSubjects() {
|
||||
const { object: clusterRoleBinding, openConfirmDialog } = this.props;
|
||||
const { object: clusterRoleBinding, openConfirmDialog, clusterRoleBindingStore } = this.props;
|
||||
const { selectedSubjects } = this;
|
||||
|
||||
openConfirmDialog({
|
||||
@@ -65,7 +69,7 @@ class NonInjectedClusterRoleBindingDetails extends React.Component<ClusterRoleBi
|
||||
|
||||
render() {
|
||||
const { selectedSubjects } = this;
|
||||
const { object: clusterRoleBinding } = this.props;
|
||||
const { object: clusterRoleBinding, openClusterRoleBindingDialog } = this.props;
|
||||
|
||||
if (!clusterRoleBinding) {
|
||||
return null;
|
||||
@@ -121,7 +125,7 @@ class NonInjectedClusterRoleBindingDetails extends React.Component<ClusterRoleBi
|
||||
)}
|
||||
|
||||
<AddRemoveButtons
|
||||
onAdd={() => ClusterRoleBindingDialog.open(clusterRoleBinding)}
|
||||
onAdd={() => openClusterRoleBindingDialog(clusterRoleBinding)}
|
||||
onRemove={selectedSubjects.size ? this.removeSelectedSubjects : undefined}
|
||||
addTooltip={`Add bindings to ${roleRef.name}`}
|
||||
removeTooltip={`Remove selected bindings from ${roleRef.name}`}
|
||||
@@ -135,5 +139,7 @@ export const ClusterRoleBindingDetails = withInjectables<Dependencies, ClusterRo
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
openConfirmDialog: di.inject(openConfirmDialogInjectable),
|
||||
openClusterRoleBindingDialog: di.inject(openClusterRoleBindingDialogInjectable),
|
||||
clusterRoleBindingStore: di.inject(clusterRoleBindingStoreInjectable),
|
||||
}),
|
||||
});
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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 { action } from "mobx";
|
||||
import editClusterRoleBindingNameStateInjectable from "./edit-name-state.injectable";
|
||||
import clusterRoleBindingDialogStateInjectable from "./state.injectable";
|
||||
|
||||
export type CloseClusterRoleBindingDialog = () => void;
|
||||
|
||||
const closeClusterRoleBindingDialogInjectable = getInjectable({
|
||||
id: "close-cluster-role-binding-dialog",
|
||||
instantiate: (di): CloseClusterRoleBindingDialog => {
|
||||
const state = di.inject(clusterRoleBindingDialogStateInjectable);
|
||||
const editNameState = di.inject(editClusterRoleBindingNameStateInjectable);
|
||||
|
||||
return action(() => {
|
||||
state.set({
|
||||
isOpen: false,
|
||||
});
|
||||
editNameState.set("");
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default closeClusterRoleBindingDialogInjectable;
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 { observable } from "mobx";
|
||||
|
||||
const editClusterRoleBindingNameStateInjectable = getInjectable({
|
||||
id: "edit-cluster-role-binding-name-state",
|
||||
instantiate: () => observable.box(""),
|
||||
});
|
||||
|
||||
export default editClusterRoleBindingNameStateInjectable;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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 { action } from "mobx";
|
||||
import type { ClusterRoleBinding } from "../../../../../common/k8s-api/endpoints";
|
||||
import editClusterRoleBindingNameStateInjectable from "./edit-name-state.injectable";
|
||||
import clusterRoleBindingDialogStateInjectable from "./state.injectable";
|
||||
|
||||
export type OpenClusterRoleBindingDialog = (clusterRoleBinding?: ClusterRoleBinding) => void;
|
||||
|
||||
const openClusterRoleBindingDialogInjectable = getInjectable({
|
||||
id: "open-cluster-role-binding-dialog",
|
||||
instantiate: (di): OpenClusterRoleBindingDialog => {
|
||||
const state = di.inject(clusterRoleBindingDialogStateInjectable);
|
||||
const editNameState = di.inject(editClusterRoleBindingNameStateInjectable);
|
||||
|
||||
return action((clusterRoleBinding) => {
|
||||
state.set({
|
||||
isOpen: true,
|
||||
clusterRoleBinding,
|
||||
});
|
||||
editNameState.set(clusterRoleBinding?.getName() ?? "");
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default openClusterRoleBindingDialogInjectable;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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 { observable } from "mobx";
|
||||
import type { ClusterRoleBinding } from "../../../../../common/k8s-api/endpoints";
|
||||
|
||||
export type ClusterRoleBindingDialogState = {
|
||||
isOpen: false;
|
||||
clusterRoleBinding?: undefined;
|
||||
} | {
|
||||
isOpen: true;
|
||||
clusterRoleBinding: ClusterRoleBinding | undefined;
|
||||
};
|
||||
|
||||
const clusterRoleBindingDialogStateInjectable = getInjectable({
|
||||
id: "cluster-role-binding-dialog-state",
|
||||
instantiate: () => observable.box<ClusterRoleBindingDialogState>({
|
||||
isOpen: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export default clusterRoleBindingDialogStateInjectable;
|
||||
File renamed without changes.
+94
-67
@@ -3,75 +3,75 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import "./dialog.scss";
|
||||
import "./view.scss";
|
||||
|
||||
import { action, computed, makeObservable, observable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { action, computed, makeObservable, observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
|
||||
import { serviceAccountStore } from "../+service-accounts/legacy-store";
|
||||
import type { ClusterRole, ClusterRoleBinding, ServiceAccount } from "../../../../common/k8s-api/endpoints";
|
||||
import type { DialogProps } from "../../dialog";
|
||||
import { Dialog } from "../../dialog";
|
||||
import { EditableList } from "../../editable-list";
|
||||
import { Icon } from "../../icon";
|
||||
import { showDetails } from "../../kube-detail-params";
|
||||
import { SubTitle } from "../../layout/sub-title";
|
||||
import { Notifications } from "../../notifications";
|
||||
import { onMultiSelectFor, Select } from "../../select";
|
||||
import { Wizard, WizardStep } from "../../wizard";
|
||||
import { clusterRoleBindingStore } from "./legacy-store";
|
||||
import { clusterRoleStore } from "../+cluster-roles/legacy-store";
|
||||
import { ObservableHashSet, nFircate } from "../../../utils";
|
||||
import { Input } from "../../input";
|
||||
import { TooltipPosition } from "../../tooltip";
|
||||
import type { Subject } from "../../../../common/k8s-api/endpoints/types/subject";
|
||||
import type { ClusterRole, ServiceAccount } from "../../../../../common/k8s-api/endpoints";
|
||||
import type { DialogProps } from "../../../dialog";
|
||||
import { Dialog } from "../../../dialog";
|
||||
import { EditableList } from "../../../editable-list";
|
||||
import { Icon } from "../../../icon";
|
||||
import { SubTitle } from "../../../layout/sub-title";
|
||||
import { onMultiSelectFor, Select } from "../../../select";
|
||||
import { Wizard, WizardStep } from "../../../wizard";
|
||||
import { ObservableHashSet, nFircate } from "../../../../utils";
|
||||
import { Input } from "../../../input";
|
||||
import { TooltipPosition } from "../../../tooltip";
|
||||
import type { Subject } from "../../../../../common/k8s-api/endpoints/types/subject";
|
||||
import type { ClusterRoleBindingDialogState } from "./state.injectable";
|
||||
import type { ClusterRoleStore } from "../../+cluster-roles/store";
|
||||
import type { ServiceAccountStore } from "../../+service-accounts/store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import clusterRoleStoreInjectable from "../../+cluster-roles/store.injectable";
|
||||
import editClusterRoleBindingNameStateInjectable from "./edit-name-state.injectable";
|
||||
import serviceAccountStoreInjectable from "../../+service-accounts/store.injectable";
|
||||
import clusterRoleBindingDialogStateInjectable from "./state.injectable";
|
||||
import type { CloseClusterRoleBindingDialog } from "./close.injectable";
|
||||
import type { OpenClusterRoleBindingDialog } from "./open.injectable";
|
||||
import openClusterRoleBindingDialogInjectable from "./open.injectable";
|
||||
import closeClusterRoleBindingDialogInjectable from "./close.injectable";
|
||||
import type { ShowDetails } from "../../../kube-detail-params/show-details.injectable";
|
||||
import type { ClusterRoleBindingStore } from "../store";
|
||||
import clusterRoleBindingStoreInjectable from "../store.injectable";
|
||||
import showDetailsInjectable from "../../../kube-detail-params/show-details.injectable";
|
||||
import type { ShowCheckedErrorNotification } from "../../../notifications/show-checked-error.injectable";
|
||||
import showCheckedErrorNotificationInjectable from "../../../notifications/show-checked-error.injectable";
|
||||
|
||||
export interface ClusterRoleBindingDialogProps extends Partial<DialogProps> {
|
||||
}
|
||||
|
||||
interface DialogState {
|
||||
isOpen: boolean;
|
||||
data?: ClusterRoleBinding;
|
||||
interface Dependencies {
|
||||
state: IObservableValue<ClusterRoleBindingDialogState>;
|
||||
editBindingNameState: IObservableValue<string>;
|
||||
clusterRoleStore: ClusterRoleStore;
|
||||
serviceAccountStore: ServiceAccountStore;
|
||||
clusterRoleBindingStore: ClusterRoleBindingStore;
|
||||
closeClusterRoleBindingDialog: CloseClusterRoleBindingDialog;
|
||||
openClusterRoleBindingDialog: OpenClusterRoleBindingDialog;
|
||||
showDetails: ShowDetails;
|
||||
showCheckedErrorNotification: ShowCheckedErrorNotification;
|
||||
}
|
||||
|
||||
const dialogState = observable.object<DialogState>({
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
@observer
|
||||
export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBindingDialogProps> {
|
||||
constructor(props: ClusterRoleBindingDialogProps) {
|
||||
class NonInjectedClusterRoleBindingDialog extends React.Component<ClusterRoleBindingDialogProps & Dependencies> {
|
||||
constructor(props: ClusterRoleBindingDialogProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.isEditing, () => {
|
||||
this.bindingName = dialogState.data?.getName() ?? "";
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
static open(roleBinding?: ClusterRoleBinding) {
|
||||
dialogState.isOpen = true;
|
||||
dialogState.data = roleBinding;
|
||||
}
|
||||
|
||||
static close() {
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
@computed get clusterRoleOptions() {
|
||||
return clusterRoleStore.items.map(clusterRole => ({
|
||||
return this.props.clusterRoleStore.items.map(clusterRole => ({
|
||||
value: clusterRole,
|
||||
label: clusterRole.getName(),
|
||||
}));
|
||||
}
|
||||
|
||||
@computed get serviceAccountOptions() {
|
||||
return serviceAccountStore.items.map(serviceAccount => ({
|
||||
return this.props.serviceAccountStore.items.map(serviceAccount => ({
|
||||
value: serviceAccount,
|
||||
label: `${serviceAccount.getName()} (${serviceAccount.getNs()})`,
|
||||
isSelected: this.selectedAccounts.has(serviceAccount),
|
||||
@@ -79,7 +79,7 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
}
|
||||
|
||||
get clusterRoleBinding() {
|
||||
return dialogState.data;
|
||||
return this.props.state.get().clusterRoleBinding;
|
||||
}
|
||||
|
||||
get isEditing() {
|
||||
@@ -87,7 +87,6 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
}
|
||||
|
||||
@observable selectedRoleRef: ClusterRole | undefined = undefined;
|
||||
@observable bindingName = "";
|
||||
selectedAccounts = new ObservableHashSet<ServiceAccount>([], sa => sa.metadata.uid);
|
||||
selectedUsers = observable.set<string>([]);
|
||||
selectedGroups = observable.set<string>([]);
|
||||
@@ -121,16 +120,15 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
return this.reset();
|
||||
}
|
||||
|
||||
this.selectedRoleRef = clusterRoleStore
|
||||
this.selectedRoleRef = this.props.clusterRoleStore
|
||||
.items
|
||||
.find(item => item.getName() === binding.roleRef.name);
|
||||
this.bindingName = binding.getName();
|
||||
|
||||
const [saSubjects, uSubjects, gSubjects] = nFircate(binding.getSubjects(), "kind", ["ServiceAccount", "User", "Group"]);
|
||||
const accountNames = new Set(saSubjects.map(acc => acc.name));
|
||||
|
||||
this.selectedAccounts.replace(
|
||||
serviceAccountStore.items
|
||||
this.props.serviceAccountStore.items
|
||||
.filter(sa => accountNames.has(sa.getName())),
|
||||
);
|
||||
this.selectedUsers.replace(uSubjects.map(user => user.name));
|
||||
@@ -139,14 +137,19 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
|
||||
reset = action(() => {
|
||||
this.selectedRoleRef = undefined;
|
||||
this.bindingName = "";
|
||||
this.selectedAccounts.clear();
|
||||
this.selectedUsers.clear();
|
||||
this.selectedGroups.clear();
|
||||
});
|
||||
|
||||
createBindings = async () => {
|
||||
const { selectedRoleRef, selectedBindings, bindingName, clusterRoleBinding } = this;
|
||||
const {
|
||||
closeClusterRoleBindingDialog,
|
||||
clusterRoleBindingStore,
|
||||
editBindingNameState,
|
||||
showDetails,
|
||||
} = this.props;
|
||||
const { selectedRoleRef, selectedBindings, clusterRoleBinding } = this;
|
||||
|
||||
if (!clusterRoleBinding || !selectedRoleRef) {
|
||||
return;
|
||||
@@ -155,7 +158,7 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
try {
|
||||
const { selfLink } = this.isEditing
|
||||
? await clusterRoleBindingStore.updateSubjects(clusterRoleBinding, selectedBindings)
|
||||
: await clusterRoleBindingStore.create({ name: bindingName }, {
|
||||
: await clusterRoleBindingStore.create({ name: editBindingNameState.get() }, {
|
||||
subjects: selectedBindings,
|
||||
roleRef: {
|
||||
name: selectedRoleRef.getName(),
|
||||
@@ -164,9 +167,9 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
});
|
||||
|
||||
showDetails(selfLink);
|
||||
ClusterRoleBindingDialog.close();
|
||||
closeClusterRoleBindingDialog();
|
||||
} catch (err) {
|
||||
Notifications.checkedError(err, `Unknown error occured while ${this.isEditing ? "editing the" : "creating a"} ClusterRoleBinding`);
|
||||
this.props.showCheckedErrorNotification(err, `Unknown error occured while ${this.isEditing ? "editing the" : "creating a"} ClusterRoleBinding`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -198,9 +201,10 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
)}
|
||||
onChange={option => {
|
||||
this.selectedRoleRef = option?.value;
|
||||
const bindingName = this.props.editBindingNameState.get();
|
||||
|
||||
if (!this.selectedRoleRef || this.bindingName === this.selectedRoleRef.getName()) {
|
||||
this.bindingName = option?.value?.getName() ?? "";
|
||||
if (!this.selectedRoleRef || bindingName === this.selectedRoleRef.getName()) {
|
||||
this.props.editBindingNameState.set(option?.value?.getName() ?? "");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -209,8 +213,8 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
<Input
|
||||
placeholder="Name of ClusterRoleBinding ..."
|
||||
disabled={this.isEditing}
|
||||
value={this.bindingName}
|
||||
onChange={val => this.bindingName = val}
|
||||
value={this.props.editBindingNameState.get()}
|
||||
onChange={val => this.props.editBindingNameState.set(val)}
|
||||
/>
|
||||
|
||||
<SubTitle title="Binding targets" />
|
||||
@@ -252,16 +256,24 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
}
|
||||
|
||||
render() {
|
||||
const { ...dialogProps } = this.props;
|
||||
const {
|
||||
closeClusterRoleBindingDialog,
|
||||
openClusterRoleBindingDialog,
|
||||
clusterRoleStore,
|
||||
editBindingNameState,
|
||||
serviceAccountStore,
|
||||
state,
|
||||
...dialogProps
|
||||
} = this.props;
|
||||
const [action, nextLabel] = this.isEditing ? ["Edit", "Update"] : ["Add", "Create"];
|
||||
const disableNext = !this.selectedRoleRef || !this.selectedBindings.length || !this.bindingName;
|
||||
const disableNext = !this.selectedRoleRef || !this.selectedBindings.length || !editBindingNameState.get();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddClusterRoleBindingDialog"
|
||||
isOpen={dialogState.isOpen}
|
||||
close={ClusterRoleBindingDialog.close}
|
||||
isOpen={state.get().isOpen}
|
||||
close={closeClusterRoleBindingDialog}
|
||||
onClose={this.reset}
|
||||
onOpen={this.onOpen}
|
||||
>
|
||||
@@ -271,7 +283,7 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
{`${action} ClusterRoleBinding`}
|
||||
</h5>
|
||||
)}
|
||||
done={ClusterRoleBindingDialog.close}
|
||||
done={closeClusterRoleBindingDialog}
|
||||
>
|
||||
<WizardStep
|
||||
nextLabel={nextLabel}
|
||||
@@ -285,3 +297,18 @@ export class ClusterRoleBindingDialog extends React.Component<ClusterRoleBinding
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ClusterRoleBindingDialog = withInjectables<Dependencies, ClusterRoleBindingDialogProps>(NonInjectedClusterRoleBindingDialog, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
clusterRoleStore: di.inject(clusterRoleStoreInjectable),
|
||||
editBindingNameState: di.inject(editClusterRoleBindingNameStateInjectable),
|
||||
serviceAccountStore: di.inject(serviceAccountStoreInjectable),
|
||||
state: di.inject(clusterRoleBindingDialogStateInjectable),
|
||||
clusterRoleBindingStore: di.inject(clusterRoleBindingStoreInjectable),
|
||||
openClusterRoleBindingDialog: di.inject(openClusterRoleBindingDialogInjectable),
|
||||
closeClusterRoleBindingDialog: di.inject(closeClusterRoleBindingDialogInjectable),
|
||||
showDetails: di.inject(showDetailsInjectable),
|
||||
showCheckedErrorNotification: di.inject(showCheckedErrorNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -4,4 +4,4 @@
|
||||
*/
|
||||
export * from "./view";
|
||||
export * from "./details";
|
||||
export * from "./dialog";
|
||||
export * from "./dialog/view";
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import clusterRoleBindingStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(clusterRoleBindingStoreInjectable)` instead
|
||||
*/
|
||||
export const clusterRoleBindingStore = asLegacyGlobalForExtensionApi(clusterRoleBindingStoreInjectable);
|
||||
@@ -9,6 +9,7 @@ import clusterRoleBindingApiInjectable from "../../../../common/k8s-api/endpoint
|
||||
import { kubeObjectStoreInjectionToken } from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import { ClusterRoleBindingStore } from "./store";
|
||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
|
||||
const clusterRoleBindingStoreInjectable = getInjectable({
|
||||
id: "cluster-role-binding-store",
|
||||
@@ -19,6 +20,7 @@ const clusterRoleBindingStoreInjectable = getInjectable({
|
||||
|
||||
return new ClusterRoleBindingStore({
|
||||
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
|
||||
@@ -9,12 +9,18 @@ import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import { KubeObjectListLayout } from "../../kube-object-list-layout";
|
||||
import { KubeObjectStatusIcon } from "../../kube-object-status-icon";
|
||||
import { ClusterRoleBindingDialog } from "./dialog";
|
||||
import { clusterRoleBindingStore } from "./legacy-store";
|
||||
import { clusterRoleStore } from "../+cluster-roles/legacy-store";
|
||||
import { serviceAccountStore } from "../+service-accounts/legacy-store";
|
||||
import { ClusterRoleBindingDialog } from "./dialog/view";
|
||||
import { SiblingsInTabLayout } from "../../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../../kube-object/age";
|
||||
import type { ClusterRoleBindingStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import clusterRoleBindingStoreInjectable from "./store.injectable";
|
||||
import type { ClusterRoleStore } from "../+cluster-roles/store";
|
||||
import type { ServiceAccountStore } from "../+service-accounts/store";
|
||||
import clusterRoleStoreInjectable from "../+cluster-roles/store.injectable";
|
||||
import serviceAccountStoreInjectable from "../+service-accounts/store.injectable";
|
||||
import type { OpenClusterRoleBindingDialog } from "./dialog/open.injectable";
|
||||
import openClusterRoleBindingDialogInjectable from "./dialog/open.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@@ -23,9 +29,23 @@ enum columnId {
|
||||
age = "age",
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
clusterRoleBindingStore: ClusterRoleBindingStore;
|
||||
clusterRoleStore: ClusterRoleStore;
|
||||
serviceAccountStore: ServiceAccountStore;
|
||||
openClusterRoleBindingDialog: OpenClusterRoleBindingDialog;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ClusterRoleBindings extends React.Component {
|
||||
class NonInjectedClusterRoleBindings extends React.Component<Dependencies> {
|
||||
render() {
|
||||
const {
|
||||
clusterRoleBindingStore,
|
||||
clusterRoleStore,
|
||||
serviceAccountStore,
|
||||
openClusterRoleBindingDialog,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
<KubeObjectListLayout
|
||||
@@ -57,7 +77,7 @@ export class ClusterRoleBindings extends React.Component {
|
||||
<KubeObjectAge key="age" object={binding} />,
|
||||
]}
|
||||
addRemoveButtons={{
|
||||
onAdd: () => ClusterRoleBindingDialog.open(),
|
||||
onAdd: () => openClusterRoleBindingDialog(),
|
||||
addTooltip: "Create new ClusterRoleBinding",
|
||||
}}
|
||||
/>
|
||||
@@ -66,3 +86,13 @@ export class ClusterRoleBindings extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ClusterRoleBindings = withInjectables<Dependencies>(NonInjectedClusterRoleBindings, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
clusterRoleBindingStore: di.inject(clusterRoleBindingStoreInjectable),
|
||||
clusterRoleStore: di.inject(clusterRoleStoreInjectable),
|
||||
serviceAccountStore: di.inject(serviceAccountStoreInjectable),
|
||||
openClusterRoleBindingDialog: di.inject(openClusterRoleBindingDialogInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import "./add-dialog.scss";
|
||||
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
|
||||
import type { DialogProps } from "../../dialog";
|
||||
import { Dialog } from "../../dialog";
|
||||
import { Input } from "../../input";
|
||||
import { showDetails } from "../../kube-detail-params";
|
||||
import { SubTitle } from "../../layout/sub-title";
|
||||
import { Notifications } from "../../notifications";
|
||||
import { Wizard, WizardStep } from "../../wizard";
|
||||
import { clusterRoleStore } from "./legacy-store";
|
||||
|
||||
export interface AddClusterRoleDialogProps extends Partial<DialogProps> {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class AddClusterRoleDialog extends React.Component<AddClusterRoleDialogProps> {
|
||||
static isOpen = observable.box(false);
|
||||
|
||||
@observable clusterRoleName = "";
|
||||
|
||||
constructor(props: AddClusterRoleDialogProps) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
AddClusterRoleDialog.isOpen.set(true);
|
||||
}
|
||||
|
||||
static close() {
|
||||
AddClusterRoleDialog.isOpen.set(false);
|
||||
}
|
||||
|
||||
reset = () => {
|
||||
this.clusterRoleName = "";
|
||||
};
|
||||
|
||||
createRole = async () => {
|
||||
try {
|
||||
const role = await clusterRoleStore.create({ name: this.clusterRoleName });
|
||||
|
||||
showDetails(role.selfLink);
|
||||
this.reset();
|
||||
AddClusterRoleDialog.close();
|
||||
} catch (error) {
|
||||
Notifications.checkedError(error, "Unknown error occured while creating the role");
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { ...dialogProps } = this.props;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddClusterRoleDialog"
|
||||
isOpen={AddClusterRoleDialog.isOpen.get()}
|
||||
close={AddClusterRoleDialog.close}
|
||||
>
|
||||
<Wizard
|
||||
header={<h5>Create ClusterRole</h5>}
|
||||
done={AddClusterRoleDialog.close}
|
||||
>
|
||||
<WizardStep
|
||||
contentClass="flex gaps column"
|
||||
nextLabel="Create"
|
||||
next={this.createRole}
|
||||
>
|
||||
<SubTitle title="ClusterRole Name" />
|
||||
<Input
|
||||
required
|
||||
autoFocus
|
||||
placeholder="Name"
|
||||
iconLeft="supervisor_account"
|
||||
value={this.clusterRoleName}
|
||||
onChange={v => this.clusterRoleName = v}
|
||||
/>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 530 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user