mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge remote-tracking branch 'origin/master' into mobx-6.2
# Conflicts: # src/common/hotbar-store.ts
This commit is contained in:
commit
426cb48966
40 files changed
+525
-158
No files matched your search
@@ -50,7 +50,7 @@ describe("kube auth proxy tests", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
UserStore.resetInstance();
|
||||
UserStore.getInstanceOrCreate();
|
||||
UserStore.createInstance();
|
||||
});
|
||||
|
||||
it("calling exit multiple times shouldn't throw", async () => {
|
||||
|
||||
@@ -76,7 +76,7 @@ describe("kubeconfig manager tests", () => {
|
||||
});
|
||||
const contextHandler = new ContextHandler(cluster);
|
||||
const port = await getFreePort();
|
||||
const kubeConfManager = await KubeconfigManager.create(cluster, contextHandler, port);
|
||||
const kubeConfManager = new KubeconfigManager(cluster, contextHandler, port);
|
||||
|
||||
expect(logger.error).not.toBeCalled();
|
||||
expect(await kubeConfManager.getPath()).toBe(`tmp${path.sep}kubeconfig-foo`);
|
||||
@@ -98,13 +98,15 @@ describe("kubeconfig manager tests", () => {
|
||||
});
|
||||
const contextHandler = new ContextHandler(cluster);
|
||||
const port = await getFreePort();
|
||||
const kubeConfManager = await KubeconfigManager.create(cluster, contextHandler, port);
|
||||
const kubeConfManager = new KubeconfigManager(cluster, contextHandler, port);
|
||||
const configPath = await kubeConfManager.getPath();
|
||||
|
||||
expect(await fse.pathExists(configPath)).toBe(true);
|
||||
await kubeConfManager.unlink();
|
||||
expect(await fse.pathExists(configPath)).toBe(false);
|
||||
await kubeConfManager.unlink(); // doesn't throw
|
||||
expect(await kubeConfManager.getPath()).toBeUndefined();
|
||||
expect(async () => {
|
||||
await kubeConfManager.getPath();
|
||||
}).rejects.toThrow("already unlinked");
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { autoUpdater, UpdateInfo } from "electron-updater";
|
||||
import logger from "./logger";
|
||||
import { isDevelopment, isTestEnv } from "../common/vars";
|
||||
import { isDevelopment, isPublishConfigured, isTestEnv } from "../common/vars";
|
||||
import { delay } from "../common/utils";
|
||||
import { areArgsUpdateAvailableToBackchannel, AutoUpdateLogPrefix, broadcastMessage, onceCorrect, UpdateAvailableChannel, UpdateAvailableToBackchannel } from "../common/ipc";
|
||||
import { once } from "lodash";
|
||||
@@ -8,6 +8,10 @@ import { app, ipcMain } from "electron";
|
||||
|
||||
let installVersion: null | string = null;
|
||||
|
||||
export function isAutoUpdateEnabled() {
|
||||
return autoUpdater.isUpdaterActive() && isPublishConfigured;
|
||||
}
|
||||
|
||||
function handleAutoUpdateBackChannel(event: Electron.IpcMainEvent, ...[arg]: UpdateAvailableToBackchannel) {
|
||||
if (arg.doUpdate) {
|
||||
if (arg.now) {
|
||||
|
||||
+1
-1
@@ -293,7 +293,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
try {
|
||||
this.initializing = true;
|
||||
this.contextHandler = new ContextHandler(this);
|
||||
this.kubeconfigManager = await KubeconfigManager.create(this, this.contextHandler, port);
|
||||
this.kubeconfigManager = new KubeconfigManager(this, this.contextHandler, port);
|
||||
this.kubeProxyUrl = `http://localhost:${port}${apiKubePrefix}`;
|
||||
this.initialized = true;
|
||||
logger.info(`[CLUSTER]: "${this.contextName}" init success`, {
|
||||
|
||||
+24
-25
@@ -6,7 +6,7 @@ import "../common/prometheus-providers";
|
||||
import * as Mobx from "mobx";
|
||||
import * as LensExtensions from "../extensions/core-api";
|
||||
import { app, autoUpdater, ipcMain, dialog, powerMonitor } from "electron";
|
||||
import { appName, isMac } from "../common/vars";
|
||||
import { appName, isMac, productName } from "../common/vars";
|
||||
import path from "path";
|
||||
import { LensProxy } from "./lens-proxy";
|
||||
import { WindowManager } from "./window-manager";
|
||||
@@ -38,12 +38,12 @@ const workingDir = path.join(app.getPath("appData"), appName);
|
||||
|
||||
app.setName(appName);
|
||||
|
||||
logger.info("📟 Setting Lens as protocol client for lens://");
|
||||
logger.info(`📟 Setting ${productName} as protocol client for lens://`);
|
||||
|
||||
if (app.setAsDefaultProtocolClient("lens")) {
|
||||
logger.info("📟 succeeded ✅");
|
||||
logger.info("📟 Protocol client register succeeded ✅");
|
||||
} else {
|
||||
logger.info("📟 failed ❗");
|
||||
logger.info("📟 Protocol client register failed ❗");
|
||||
}
|
||||
|
||||
if (!process.env.CICD) {
|
||||
@@ -63,7 +63,7 @@ if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
app.exit();
|
||||
} else {
|
||||
const lprm = LensProtocolRouterMain.getInstanceOrCreate();
|
||||
const lprm = LensProtocolRouterMain.createInstance();
|
||||
|
||||
for (const arg of process.argv) {
|
||||
if (arg.toLowerCase().startsWith("lens://")) {
|
||||
@@ -74,7 +74,7 @@ if (!app.requestSingleInstanceLock()) {
|
||||
}
|
||||
|
||||
app.on("second-instance", (event, argv) => {
|
||||
const lprm = LensProtocolRouterMain.getInstanceOrCreate();
|
||||
const lprm = LensProtocolRouterMain.createInstance();
|
||||
|
||||
for (const arg of argv) {
|
||||
if (arg.toLowerCase().startsWith("lens://")) {
|
||||
@@ -87,7 +87,7 @@ app.on("second-instance", (event, argv) => {
|
||||
});
|
||||
|
||||
app.on("ready", async () => {
|
||||
logger.info(`🚀 Starting Lens from "${workingDir}"`);
|
||||
logger.info(`🚀 Starting ${productName} from "${workingDir}"`);
|
||||
logger.info("🐚 Syncing shell environment");
|
||||
await shellSync();
|
||||
|
||||
@@ -99,11 +99,11 @@ app.on("ready", async () => {
|
||||
|
||||
registerFileProtocol("static", __static);
|
||||
|
||||
const userStore = UserStore.getInstanceOrCreate();
|
||||
const clusterStore = ClusterStore.getInstanceOrCreate();
|
||||
const hotbarStore = HotbarStore.getInstanceOrCreate();
|
||||
const extensionsStore = ExtensionsStore.getInstanceOrCreate();
|
||||
const filesystemStore = FilesystemProvisionerStore.getInstanceOrCreate();
|
||||
const userStore = UserStore.createInstance();
|
||||
const clusterStore = ClusterStore.createInstance();
|
||||
const hotbarStore = HotbarStore.createInstance();
|
||||
const extensionsStore = ExtensionsStore.createInstance();
|
||||
const filesystemStore = FilesystemProvisionerStore.createInstance();
|
||||
|
||||
logger.info("💾 Loading stores");
|
||||
// preload
|
||||
@@ -115,36 +115,35 @@ app.on("ready", async () => {
|
||||
filesystemStore.load(),
|
||||
]);
|
||||
|
||||
// find free port
|
||||
let proxyPort;
|
||||
|
||||
try {
|
||||
logger.info("🔑 Getting free port for LensProxy server");
|
||||
proxyPort = await getFreePort();
|
||||
const proxyPort = await getFreePort();
|
||||
|
||||
// create cluster manager
|
||||
ClusterManager.createInstance(proxyPort);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy");
|
||||
app.exit();
|
||||
}
|
||||
|
||||
// create cluster manager
|
||||
ClusterManager.getInstanceOrCreate(proxyPort);
|
||||
const clusterManager = ClusterManager.getInstance();
|
||||
|
||||
// run proxy
|
||||
try {
|
||||
logger.info("🔌 Starting LensProxy");
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars-ts
|
||||
LensProxy.getInstanceOrCreate(proxyPort).listen();
|
||||
LensProxy.createInstance(clusterManager.port).listen();
|
||||
} catch (error) {
|
||||
logger.error(`Could not start proxy (127.0.0:${proxyPort}): ${error?.message}`);
|
||||
dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${proxyPort}): ${error?.message || "unknown error"}`);
|
||||
logger.error(`Could not start proxy (127.0.0:${clusterManager.port}): ${error?.message}`);
|
||||
dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${clusterManager.port}): ${error?.message || "unknown error"}`);
|
||||
app.exit();
|
||||
}
|
||||
|
||||
// test proxy connection
|
||||
try {
|
||||
logger.info("🔎 Testing LensProxy connection ...");
|
||||
const versionFromProxy = await getAppVersionFromProxyServer(proxyPort);
|
||||
const versionFromProxy = await getAppVersionFromProxyServer(clusterManager.port);
|
||||
|
||||
if (getAppVersion() !== versionFromProxy) {
|
||||
logger.error(`Proxy server responded with invalid response`);
|
||||
@@ -154,9 +153,9 @@ app.on("ready", async () => {
|
||||
logger.error("Checking proxy server connection failed", error);
|
||||
}
|
||||
|
||||
const extensionDiscovery = ExtensionDiscovery.getInstanceOrCreate();
|
||||
const extensionDiscovery = ExtensionDiscovery.createInstance();
|
||||
|
||||
ExtensionLoader.getInstanceOrCreate().init();
|
||||
ExtensionLoader.createInstance().init();
|
||||
extensionDiscovery.init();
|
||||
|
||||
// Start the app without showing the main window when auto starting on login
|
||||
@@ -164,7 +163,7 @@ app.on("ready", async () => {
|
||||
const startHidden = process.argv.includes("--hidden") || (isMac && app.getLoginItemSettings().wasOpenedAsHidden);
|
||||
|
||||
logger.info("🖥️ Starting WindowManager");
|
||||
const windowManager = WindowManager.getInstanceOrCreate(proxyPort);
|
||||
const windowManager = WindowManager.createInstance(clusterManager.port);
|
||||
|
||||
installDeveloperTools();
|
||||
|
||||
|
||||
@@ -9,16 +9,39 @@ import logger from "./logger";
|
||||
|
||||
export class KubeconfigManager {
|
||||
protected configDir = app.getPath("temp");
|
||||
protected tempFile: string;
|
||||
protected tempFile: string = null;
|
||||
|
||||
private constructor(protected cluster: Cluster, protected contextHandler: ContextHandler, protected port: number) { }
|
||||
constructor(protected cluster: Cluster, protected contextHandler: ContextHandler, protected port: number) { }
|
||||
|
||||
static async create(cluster: Cluster, contextHandler: ContextHandler, port: number) {
|
||||
const kcm = new KubeconfigManager(cluster, contextHandler, port);
|
||||
async getPath(): Promise<string> {
|
||||
if (this.tempFile === undefined) {
|
||||
throw new Error("kubeconfig is already unlinked");
|
||||
}
|
||||
|
||||
await kcm.init();
|
||||
if (!this.tempFile) {
|
||||
await this.init();
|
||||
}
|
||||
|
||||
return kcm;
|
||||
// create proxy kubeconfig if it is removed without unlink called
|
||||
if (!(await fs.pathExists(this.tempFile))) {
|
||||
try {
|
||||
this.tempFile = await this.createProxyKubeconfig();
|
||||
} catch (err) {
|
||||
logger.error(`Failed to created temp config for auth-proxy`, { err });
|
||||
}
|
||||
}
|
||||
|
||||
return this.tempFile;
|
||||
}
|
||||
|
||||
async unlink() {
|
||||
if (!this.tempFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Deleting temporary kubeconfig: ${this.tempFile}`);
|
||||
await fs.unlink(this.tempFile);
|
||||
this.tempFile = undefined;
|
||||
}
|
||||
|
||||
protected async init() {
|
||||
@@ -30,20 +53,6 @@ export class KubeconfigManager {
|
||||
}
|
||||
}
|
||||
|
||||
async getPath() {
|
||||
// create proxy kubeconfig if it is removed
|
||||
if (this.tempFile !== undefined && !(await fs.pathExists(this.tempFile))) {
|
||||
try {
|
||||
this.tempFile = await this.createProxyKubeconfig();
|
||||
} catch (err) {
|
||||
logger.error(`Failed to created temp config for auth-proxy`, { err });
|
||||
}
|
||||
}
|
||||
|
||||
return this.tempFile;
|
||||
|
||||
}
|
||||
|
||||
protected resolveProxyUrl() {
|
||||
return `http://127.0.0.1:${this.port}/${this.cluster.id}`;
|
||||
}
|
||||
@@ -87,14 +96,4 @@ export class KubeconfigManager {
|
||||
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
async unlink() {
|
||||
if (!this.tempFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Deleting temporary kubeconfig: ${this.tempFile}`);
|
||||
await fs.unlink(this.tempFile);
|
||||
this.tempFile = undefined;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { app, BrowserWindow, dialog, ipcMain, IpcMainEvent, Menu, MenuItem, MenuItemConstructorOptions, webContents, shell } from "electron";
|
||||
import { autorun } from "mobx";
|
||||
import { WindowManager } from "./window-manager";
|
||||
import { appName, isMac, isWindows, isTestEnv, docsUrl, supportUrl } from "../common/vars";
|
||||
import { appName, isMac, isWindows, isTestEnv, docsUrl, supportUrl, productName } from "../common/vars";
|
||||
import { addClusterURL } from "../renderer/components/+add-cluster/add-cluster.route";
|
||||
import { preferencesURL } from "../renderer/components/+preferences/preferences.route";
|
||||
import { whatsNewURL } from "../renderer/components/+whats-new/whats-new.route";
|
||||
@@ -34,7 +34,7 @@ export function showAbout(browserWindow: BrowserWindow) {
|
||||
title: `${isWindows ? " ".repeat(2) : ""}${appName}`,
|
||||
type: "info",
|
||||
buttons: ["Close"],
|
||||
message: `Lens`,
|
||||
message: productName,
|
||||
detail: appInfo.join("\r\n")
|
||||
});
|
||||
}
|
||||
@@ -55,7 +55,7 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
label: app.getName(),
|
||||
submenu: [
|
||||
{
|
||||
label: "About Lens",
|
||||
label: `About ${productName}`,
|
||||
click(menuItem: MenuItem, browserWindow: BrowserWindow) {
|
||||
showAbout(browserWindow);
|
||||
}
|
||||
@@ -220,7 +220,7 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
},
|
||||
...ignoreOnMac([
|
||||
{
|
||||
label: "About Lens",
|
||||
label: `About ${productName}`,
|
||||
click(menuItem: MenuItem, browserWindow: BrowserWindow) {
|
||||
showAbout(browserWindow);
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ function throwIfDefined(val: any): void {
|
||||
|
||||
describe("protocol router tests", () => {
|
||||
beforeEach(() => {
|
||||
ExtensionsStore.getInstanceOrCreate();
|
||||
ExtensionLoader.getInstanceOrCreate();
|
||||
ExtensionsStore.createInstance();
|
||||
ExtensionLoader.createInstance();
|
||||
|
||||
const lpr = LensProtocolRouterMain.getInstanceOrCreate();
|
||||
const lpr = LensProtocolRouterMain.createInstance();
|
||||
|
||||
lpr.extensionsLoaded = true;
|
||||
lpr.rendererLoaded = true;
|
||||
|
||||
+15
-9
@@ -3,11 +3,11 @@ import packageInfo from "../../package.json";
|
||||
import { Menu, Tray } from "electron";
|
||||
import { autorun } from "mobx";
|
||||
import { showAbout } from "./menu";
|
||||
import { checkForUpdates } from "./app-updater";
|
||||
import { checkForUpdates, isAutoUpdateEnabled } from "./app-updater";
|
||||
import { WindowManager } from "./window-manager";
|
||||
import { preferencesURL } from "../renderer/components/+preferences/preferences.route";
|
||||
import logger from "./logger";
|
||||
import { isDevelopment, isWindows } from "../common/vars";
|
||||
import { isDevelopment, isWindows, productName } from "../common/vars";
|
||||
import { exitApp } from "./exit-app";
|
||||
|
||||
const TRAY_LOG_PREFIX = "[TRAY]";
|
||||
@@ -58,9 +58,9 @@ export function initTray(windowManager: WindowManager) {
|
||||
}
|
||||
|
||||
function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
return Menu.buildFromTemplate([
|
||||
const template: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: "Open Lens",
|
||||
label: `Open ${productName}`,
|
||||
click() {
|
||||
windowManager
|
||||
.ensureMainWindow()
|
||||
@@ -74,16 +74,22 @@ function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
.navigate(preferencesURL())
|
||||
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to nativate to Preferences`, { error }));
|
||||
},
|
||||
},
|
||||
{
|
||||
}
|
||||
];
|
||||
|
||||
if (isAutoUpdateEnabled()) {
|
||||
template.push({
|
||||
label: "Check for updates",
|
||||
click() {
|
||||
checkForUpdates()
|
||||
.then(() => windowManager.ensureMainWindow());
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return Menu.buildFromTemplate(template.concat([
|
||||
{
|
||||
label: "About Lens",
|
||||
label: `About ${productName}`,
|
||||
click() {
|
||||
windowManager.ensureMainWindow()
|
||||
.then(showAbout)
|
||||
@@ -97,5 +103,5 @@ function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
exitApp();
|
||||
}
|
||||
}
|
||||
]);
|
||||
]));
|
||||
}
|
||||
Reference in new issue
Block a user