mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Making apiBase injectable (#6022)
* Making apiBase injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert all of Helm functions to be DI Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make PortForward's use of apiBase fully injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert all metric requests to be injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace resource applier with injectables Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch KubeJsonApi.forCluster to be injectable but do not use Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert the rest of shell sessions to be DI-ed - This is a prerequesit for using the new createKubeJsonApiForClusterInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Use new createKubeJsonApiForClusterInjectable for openNodeShellSession Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make KubeconfigDialog injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove jest-fetch-mock and make fetch injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests with new global override Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add new injectable for create KubeJsonApi and JsonApi instances Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix showing-details-for-helm-release behavioural tests - Remove HelmChartStore in favour of all injectables - Create a model for UpgradeChartDockTab Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix show details and updating helm releases tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix residual typing issues related to metrics Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix crash on load due to circular dependency Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix create resource tab not working Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove legacy apiBase global Signed-off-by: Sebastian Malton <sebastian@malton.name> * Introduce and use isDebuggingInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Introduce and use windowLocationInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove global legacy apiKube Signed-off-by: Sebastian Malton <sebastian@malton.name> * Improve injectable filenames compared to the injectables inside Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove modifying input in requestActivePortForwardInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Introduce and use get(Milli)SecondsFromUnixEpochInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch to non-reactive way of gettting possible helm release versions Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix typo Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix bug in KubeApi constructor Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert all KubeApi related tests to use asyncFn Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix unit tests after introducing new injectables that have side effects Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix bad rebase causing tests to fail Signed-off-by: Sebastian Malton <sebastian@malton.name> * Improve expects for multiple field values Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix crash will looking up api refs Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix breaking change on KubeApi.list Signed-off-by: Sebastian Malton <sebastian@malton.name> * Better fix for formatting urls Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove injectable for time since we should just use useMockTime Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add happy path behavioural tests for upgrade chart tab Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove debug message Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix showing-details-for-helm-release tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix installing-helm-chart-from-new-tab tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests relating to hosted cluster id Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots to recent changes in master Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Reupdated upgrade chart new tab test snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix flakiness in unit test when using <Animated> Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix flakiness and improve tests for DeleteClusterDialog Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix kubeconfig-sync tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix <Extensions> tests by removing mockFs and making everything injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix build issues Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix getElectronAppPathInjectable override not returning absolute paths - Also fixes the listing-active-helm-repos-in-prefs tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace all uses of getAbsolutePath with joinPaths as it is more correct and less confusing Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix opening application window tests by making override properly absolute Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots relating no longer using getAbsolutePath Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix and add behavioural tests for RenderDelay Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix extension discovery tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix test flakiness because of path side effects, propagate uses to as many places Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix extension-discovery tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override to fix some tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Rewrite and fix implementation of KubeconfigManager and its tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests by global override pathExists Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix unit tests failing on windows by using injectable verions of path functions Signed-off-by: Sebastian Malton <sebastian@malton.name> * Attempt to fix test timeout by using runInAction Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots after rebase Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots after rebase Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests after rebase Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix setupIpcMainHandlers usage 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> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> Co-authored-by: Iku-turso <mikko.aspiala@gmail.com>
This commit is contained in:
367 files changed
+16701
-5302
No files matched your search
@@ -5,121 +5,95 @@
|
||||
|
||||
import styles from "./kubeconfig-dialog.module.scss";
|
||||
import React from "react";
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import yaml from "js-yaml";
|
||||
import type { ServiceAccount } from "../../../common/k8s-api/endpoints";
|
||||
import { cssNames, saveFileDialog } from "../../utils";
|
||||
import { Button } from "../button";
|
||||
import type { DialogProps } from "../dialog";
|
||||
import { Dialog } from "../dialog";
|
||||
import { Icon } from "../icon";
|
||||
import { Notifications } from "../notifications";
|
||||
import type { ShowNotification } from "../notifications";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
import { apiBase } from "../../api";
|
||||
import { MonacoEditor } from "../monaco-editor";
|
||||
import { clipboard } from "electron";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable";
|
||||
import kubeconfigDialogStateInjectable from "./state.injectable";
|
||||
|
||||
export interface KubeconfigDialogData {
|
||||
title?: React.ReactNode;
|
||||
loader: () => Promise<any>;
|
||||
config: string;
|
||||
}
|
||||
|
||||
export interface KubeConfigDialogProps extends Partial<DialogProps> {
|
||||
}
|
||||
|
||||
const dialogState = observable.box<KubeconfigDialogData | undefined>();
|
||||
interface Dependencies {
|
||||
state: IObservableValue<KubeconfigDialogData | undefined>;
|
||||
showSuccessNotification: ShowNotification;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class KubeConfigDialog extends React.Component<KubeConfigDialogProps> {
|
||||
@observable config = ""; // parsed kubeconfig in yaml format
|
||||
|
||||
constructor(props: KubeConfigDialogProps) {
|
||||
class NonInjectedKubeConfigDialog extends React.Component<KubeConfigDialogProps & Dependencies> {
|
||||
constructor(props: KubeConfigDialogProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open(data: KubeconfigDialogData) {
|
||||
dialogState.set(data);
|
||||
}
|
||||
|
||||
static close() {
|
||||
dialogState.set(undefined);
|
||||
}
|
||||
|
||||
close = () => {
|
||||
KubeConfigDialog.close();
|
||||
this.props.state.set(undefined);
|
||||
};
|
||||
|
||||
onOpen = (data: KubeconfigDialogData) => {
|
||||
this.loadConfig(data);
|
||||
copyToClipboard = (config: string) => {
|
||||
clipboard.writeText(config);
|
||||
this.props.showSuccessNotification("Config copied to clipboard");
|
||||
};
|
||||
|
||||
async loadConfig(data: KubeconfigDialogData) {
|
||||
const config = await data.loader().catch(err => {
|
||||
Notifications.error(err);
|
||||
this.close();
|
||||
});
|
||||
|
||||
this.config = config ? yaml.dump(config) : "";
|
||||
}
|
||||
|
||||
copyToClipboard = () => {
|
||||
clipboard.writeText(this.config);
|
||||
Notifications.ok("Config copied to clipboard");
|
||||
download = (config: string) => {
|
||||
saveFileDialog("config", config, "text/yaml");
|
||||
};
|
||||
|
||||
download = () => {
|
||||
saveFileDialog("config", this.config, "text/yaml");
|
||||
};
|
||||
|
||||
renderContents(data: KubeconfigDialogData) {
|
||||
const yamlConfig = this.config;
|
||||
|
||||
return (
|
||||
<Wizard header={<h5>{data.title || "Kubeconfig File"}</h5>}>
|
||||
<WizardStep
|
||||
customButtons={(
|
||||
<div className="actions flex gaps">
|
||||
<Button plain onClick={this.copyToClipboard}>
|
||||
<Icon material="assignment"/>
|
||||
{" Copy to clipboard"}
|
||||
</Button>
|
||||
<Button plain onClick={this.download}>
|
||||
<Icon material="cloud_download"/>
|
||||
{" Download file"}
|
||||
</Button>
|
||||
<Button
|
||||
plain
|
||||
className="box right"
|
||||
onClick={this.close}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
prev={this.close}
|
||||
>
|
||||
<MonacoEditor
|
||||
readOnly
|
||||
className={styles.editor}
|
||||
value={yamlConfig}
|
||||
/>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
);
|
||||
}
|
||||
renderContents = (data: KubeconfigDialogData) => (
|
||||
<Wizard header={<h5>{ data.title || "Kubeconfig File" }</h5>}>
|
||||
<WizardStep
|
||||
customButtons={ (
|
||||
<div className="actions flex gaps">
|
||||
<Button plain onClick={() => this.copyToClipboard(data.config)}>
|
||||
<Icon material="assignment" />
|
||||
{" Copy to clipboard"}
|
||||
</Button>
|
||||
<Button plain onClick={() => this.download(data.config)}>
|
||||
<Icon material="cloud_download" />
|
||||
{" Download file"}
|
||||
</Button>
|
||||
<Button
|
||||
plain
|
||||
className="box right"
|
||||
onClick={this.close}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
prev={this.close}
|
||||
>
|
||||
<MonacoEditor
|
||||
readOnly
|
||||
className={styles.editor}
|
||||
value={data.config}
|
||||
/>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
);
|
||||
|
||||
render() {
|
||||
const { className, ...dialogProps } = this.props;
|
||||
const data = dialogState.get();
|
||||
const { className, state, ...dialogProps } = this.props;
|
||||
const data = state.get();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className={cssNames(styles.KubeConfigDialog, className)}
|
||||
isOpen={Boolean(data)}
|
||||
onOpen={data && (() => this.onOpen(data))}
|
||||
isOpen={!!data}
|
||||
close={this.close}
|
||||
>
|
||||
{data && this.renderContents(data)}
|
||||
@@ -128,12 +102,10 @@ export class KubeConfigDialog extends React.Component<KubeConfigDialogProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export function openServiceAccountKubeConfig(account: ServiceAccount) {
|
||||
const accountName = account.getName();
|
||||
const namespace = account.getNs();
|
||||
|
||||
KubeConfigDialog.open({
|
||||
title: `${accountName} kubeconfig`,
|
||||
loader: () => apiBase.get(`/kubeconfig/service-account/${namespace}/${accountName}`),
|
||||
});
|
||||
}
|
||||
export const KubeConfigDialog = withInjectables<Dependencies, KubeConfigDialogProps>(NonInjectedKubeConfigDialog, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
showSuccessNotification: di.inject(showSuccessNotificationInjectable),
|
||||
state: di.inject(kubeconfigDialogStateInjectable),
|
||||
}),
|
||||
});
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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 { ServiceAccount } from "../../../common/k8s-api/endpoints";
|
||||
import { urlBuilderFor } from "../../../common/utils/buildUrl";
|
||||
import apiBaseInjectable from "../../k8s/api-base.injectable";
|
||||
import openKubeconfigDialogInjectable from "./open.injectable";
|
||||
|
||||
export type OpenServiceAccountKubeConfigDialog = (account: ServiceAccount) => void;
|
||||
|
||||
const serviceAccountConfigEndpoint = urlBuilderFor("/kubeconfig/service-account/:namespace/:name");
|
||||
|
||||
const openServiceAccountKubeConfigDialogInjectable = getInjectable({
|
||||
id: "open-service-account-kube-config-dialog",
|
||||
instantiate: (di): OpenServiceAccountKubeConfigDialog => {
|
||||
const apiBase = di.inject(apiBaseInjectable);
|
||||
const openKubeconfigDialog = di.inject(openKubeconfigDialogInjectable);
|
||||
|
||||
return (account) => openKubeconfigDialog({
|
||||
title: `${account.getName()} kubeconfig`,
|
||||
loader: () => apiBase.get(serviceAccountConfigEndpoint.compile({
|
||||
name: account.getName(),
|
||||
namespace: account.getNs(),
|
||||
})),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default openServiceAccountKubeConfigDialogInjectable;
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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 React from "react";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import showCheckedErrorNotificationInjectable from "../notifications/show-checked-error.injectable";
|
||||
import kubeconfigDialogStateInjectable from "./state.injectable";
|
||||
|
||||
export interface OpenKubeconfigDialogArgs {
|
||||
title?: React.ReactNode;
|
||||
loader: () => Promise<string>;
|
||||
}
|
||||
|
||||
export type OpenKubeconfigDialog = (openArgs: OpenKubeconfigDialogArgs) => void;
|
||||
|
||||
const openKubeconfigDialogInjectable = getInjectable({
|
||||
id: "open-kubeconfig-dialog",
|
||||
instantiate: (di): OpenKubeconfigDialog => {
|
||||
const state = di.inject(kubeconfigDialogStateInjectable);
|
||||
const showCheckedErrorNotification = di.inject(showCheckedErrorNotificationInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return ({ title, loader }) => {
|
||||
(async () => {
|
||||
try {
|
||||
const config = await loader();
|
||||
|
||||
state.set({ title, config });
|
||||
} catch (error) {
|
||||
showCheckedErrorNotification(error, "Failed to retrive config for dialog");
|
||||
logger.warn("[KUBEOCONFIG-DIALOG]: failed to retrived config for dialog", error);
|
||||
}
|
||||
})();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default openKubeconfigDialogInjectable;
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { observable } from "mobx";
|
||||
import type { KubeconfigDialogData } from "./kubeconfig-dialog";
|
||||
|
||||
const kubeconfigDialogStateInjectable = getInjectable({
|
||||
id: "kubeconfig-dialog-state",
|
||||
instantiate: () => observable.box<KubeconfigDialogData>(),
|
||||
});
|
||||
|
||||
export default kubeconfigDialogStateInjectable;
|
||||
Reference in new issue
Block a user