mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
add no-unused and react/recommended to eslint (#1523)
* add no-unused-vars and no-unused-imports * added quotes: double, and remove ignore pattern * move itif and describeif into utils Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
10eb082854
commit
7451869c25
199 files changed
+1178
-807
No files matched your search
@@ -13,8 +13,8 @@ describe("empty config", () => {
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({})
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({})
|
||||
}
|
||||
};
|
||||
mockFs(mockOpts);
|
||||
@@ -144,8 +144,8 @@ describe("config with existing clusters", () => {
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "99.99.99"
|
||||
@@ -153,24 +153,24 @@ describe("config with existing clusters", () => {
|
||||
},
|
||||
clusters: [
|
||||
{
|
||||
id: 'cluster1',
|
||||
kubeConfig: 'foo',
|
||||
contextName: 'foo',
|
||||
preferences: { terminalCWD: '/foo' },
|
||||
workspace: 'default'
|
||||
id: "cluster1",
|
||||
kubeConfig: "foo",
|
||||
contextName: "foo",
|
||||
preferences: { terminalCWD: "/foo" },
|
||||
workspace: "default"
|
||||
},
|
||||
{
|
||||
id: 'cluster2',
|
||||
kubeConfig: 'foo2',
|
||||
contextName: 'foo2',
|
||||
preferences: { terminalCWD: '/foo2' }
|
||||
id: "cluster2",
|
||||
kubeConfig: "foo2",
|
||||
contextName: "foo2",
|
||||
preferences: { terminalCWD: "/foo2" }
|
||||
},
|
||||
{
|
||||
id: 'cluster3',
|
||||
kubeConfig: 'foo',
|
||||
contextName: 'foo',
|
||||
preferences: { terminalCWD: '/foo' },
|
||||
workspace: 'foo'
|
||||
id: "cluster3",
|
||||
kubeConfig: "foo",
|
||||
contextName: "foo",
|
||||
preferences: { terminalCWD: "/foo" },
|
||||
workspace: "foo"
|
||||
},
|
||||
]
|
||||
})
|
||||
@@ -186,27 +186,27 @@ describe("config with existing clusters", () => {
|
||||
});
|
||||
|
||||
it("allows to retrieve a cluster", () => {
|
||||
const storedCluster = clusterStore.getById('cluster1');
|
||||
expect(storedCluster.id).toBe('cluster1');
|
||||
expect(storedCluster.preferences.terminalCWD).toBe('/foo');
|
||||
const storedCluster = clusterStore.getById("cluster1");
|
||||
expect(storedCluster.id).toBe("cluster1");
|
||||
expect(storedCluster.preferences.terminalCWD).toBe("/foo");
|
||||
});
|
||||
|
||||
it("allows to delete a cluster", () => {
|
||||
clusterStore.removeById('cluster2');
|
||||
const storedCluster = clusterStore.getById('cluster1');
|
||||
clusterStore.removeById("cluster2");
|
||||
const storedCluster = clusterStore.getById("cluster1");
|
||||
expect(storedCluster).toBeTruthy();
|
||||
const storedCluster2 = clusterStore.getById('cluster2');
|
||||
const storedCluster2 = clusterStore.getById("cluster2");
|
||||
expect(storedCluster2).toBeUndefined();
|
||||
});
|
||||
|
||||
it("allows getting all of the clusters", async () => {
|
||||
const storedClusters = clusterStore.clustersList;
|
||||
expect(storedClusters.length).toBe(3);
|
||||
expect(storedClusters[0].id).toBe('cluster1');
|
||||
expect(storedClusters[0].preferences.terminalCWD).toBe('/foo');
|
||||
expect(storedClusters[1].id).toBe('cluster2');
|
||||
expect(storedClusters[1].preferences.terminalCWD).toBe('/foo2');
|
||||
expect(storedClusters[2].id).toBe('cluster3');
|
||||
expect(storedClusters[0].id).toBe("cluster1");
|
||||
expect(storedClusters[0].preferences.terminalCWD).toBe("/foo");
|
||||
expect(storedClusters[1].id).toBe("cluster2");
|
||||
expect(storedClusters[1].preferences.terminalCWD).toBe("/foo2");
|
||||
expect(storedClusters[2].id).toBe("cluster3");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -214,14 +214,14 @@ describe("pre 2.0 config with an existing cluster", () => {
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "1.0.0"
|
||||
}
|
||||
},
|
||||
cluster1: 'kubeconfig content'
|
||||
cluster1: "kubeconfig content"
|
||||
})
|
||||
}
|
||||
};
|
||||
@@ -244,8 +244,8 @@ describe("pre 2.6.0 config with a cluster that has arrays in auth config", () =>
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "2.4.1"
|
||||
@@ -270,8 +270,8 @@ describe("pre 2.6.0 config with a cluster that has arrays in auth config", () =>
|
||||
const file = clusterStore.clustersList[0].kubeConfigPath;
|
||||
const config = fs.readFileSync(file, "utf8");
|
||||
const kc = yaml.safeLoad(config);
|
||||
expect(kc.users[0].user['auth-provider'].config['access-token']).toBe("should be string");
|
||||
expect(kc.users[0].user['auth-provider'].config['expiry']).toBe("should be string");
|
||||
expect(kc.users[0].user["auth-provider"].config["access-token"]).toBe("should be string");
|
||||
expect(kc.users[0].user["auth-provider"].config["expiry"]).toBe("should be string");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -279,8 +279,8 @@ describe("pre 2.6.0 config with a cluster icon", () => {
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "2.4.1"
|
||||
@@ -308,8 +308,8 @@ describe("pre 2.6.0 config with a cluster icon", () => {
|
||||
|
||||
it("moves the icon into preferences", async () => {
|
||||
const storedClusterData = clusterStore.clustersList[0];
|
||||
expect(storedClusterData.hasOwnProperty('icon')).toBe(false);
|
||||
expect(storedClusterData.preferences.hasOwnProperty('icon')).toBe(true);
|
||||
expect(storedClusterData.hasOwnProperty("icon")).toBe(false);
|
||||
expect(storedClusterData.preferences.hasOwnProperty("icon")).toBe(true);
|
||||
expect(storedClusterData.preferences.icon.startsWith("data:;base64,")).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -318,8 +318,8 @@ describe("for a pre 2.7.0-beta.0 config without a workspace", () => {
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "2.6.6"
|
||||
@@ -345,7 +345,7 @@ describe("for a pre 2.7.0-beta.0 config without a workspace", () => {
|
||||
|
||||
it("adds cluster to default workspace", async () => {
|
||||
const storedClusterData = clusterStore.clustersList[0];
|
||||
expect(storedClusterData.workspace).toBe('default');
|
||||
expect(storedClusterData.workspace).toBe("default");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -353,8 +353,8 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
|
||||
beforeEach(() => {
|
||||
ClusterStore.resetInstance();
|
||||
const mockOpts = {
|
||||
'tmp': {
|
||||
'lens-cluster-store.json': JSON.stringify({
|
||||
"tmp": {
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "3.5.0"
|
||||
@@ -362,9 +362,9 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
|
||||
},
|
||||
clusters: [
|
||||
{
|
||||
id: 'cluster1',
|
||||
kubeConfig: 'kubeconfig content',
|
||||
contextName: 'cluster',
|
||||
id: "cluster1",
|
||||
kubeConfig: "kubeconfig content",
|
||||
contextName: "cluster",
|
||||
preferences: {
|
||||
icon: "store://icon_path",
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ import mockFs from "mock-fs";
|
||||
jest.mock("electron", () => {
|
||||
return {
|
||||
app: {
|
||||
getVersion: () => '99.99.99',
|
||||
getPath: () => 'tmp',
|
||||
getLocale: () => 'en'
|
||||
getVersion: () => "99.99.99",
|
||||
getPath: () => "tmp",
|
||||
getLocale: () => "en"
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -18,7 +18,7 @@ describe("user store tests", () => {
|
||||
describe("for an empty config", () => {
|
||||
beforeEach(() => {
|
||||
UserStore.resetInstance();
|
||||
mockFs({ tmp: { 'config.json': "{}" } });
|
||||
mockFs({ tmp: { "config.json": "{}" } });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -35,26 +35,26 @@ describe("user store tests", () => {
|
||||
it("allows adding and listing seen contexts", () => {
|
||||
const us = UserStore.getInstance<UserStore>();
|
||||
|
||||
us.seenContexts.add('foo');
|
||||
us.seenContexts.add("foo");
|
||||
expect(us.seenContexts.size).toBe(1);
|
||||
|
||||
us.seenContexts.add('foo');
|
||||
us.seenContexts.add('bar');
|
||||
us.seenContexts.add("foo");
|
||||
us.seenContexts.add("bar");
|
||||
expect(us.seenContexts.size).toBe(2); // check 'foo' isn't added twice
|
||||
expect(us.seenContexts.has('foo')).toBe(true);
|
||||
expect(us.seenContexts.has('bar')).toBe(true);
|
||||
expect(us.seenContexts.has("foo")).toBe(true);
|
||||
expect(us.seenContexts.has("bar")).toBe(true);
|
||||
});
|
||||
|
||||
it("allows setting and getting preferences", () => {
|
||||
const us = UserStore.getInstance<UserStore>();
|
||||
|
||||
us.preferences.httpsProxy = 'abcd://defg';
|
||||
us.preferences.httpsProxy = "abcd://defg";
|
||||
|
||||
expect(us.preferences.httpsProxy).toBe('abcd://defg');
|
||||
expect(us.preferences.httpsProxy).toBe("abcd://defg");
|
||||
expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme);
|
||||
|
||||
us.preferences.colorTheme = "light";
|
||||
expect(us.preferences.colorTheme).toBe('light');
|
||||
expect(us.preferences.colorTheme).toBe("light");
|
||||
});
|
||||
|
||||
it("correctly resets theme to default value", async () => {
|
||||
@@ -80,11 +80,11 @@ describe("user store tests", () => {
|
||||
beforeEach(() => {
|
||||
UserStore.resetInstance();
|
||||
mockFs({
|
||||
'tmp': {
|
||||
'config.json': JSON.stringify({
|
||||
user: { username: 'foobar' },
|
||||
preferences: { colorTheme: 'light' },
|
||||
lastSeenAppVersion: '1.2.3'
|
||||
"tmp": {
|
||||
"config.json": JSON.stringify({
|
||||
user: { username: "foobar" },
|
||||
preferences: { colorTheme: "light" },
|
||||
lastSeenAppVersion: "1.2.3"
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -97,7 +97,7 @@ describe("user store tests", () => {
|
||||
it("sets last seen app version to 0.0.0", () => {
|
||||
const us = UserStore.getInstance<UserStore>();
|
||||
|
||||
expect(us.lastSeenAppVersion).toBe('0.0.0');
|
||||
expect(us.lastSeenAppVersion).toBe("0.0.0");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,9 +3,9 @@ import mockFs from "mock-fs";
|
||||
jest.mock("electron", () => {
|
||||
return {
|
||||
app: {
|
||||
getVersion: () => '99.99.99',
|
||||
getPath: () => 'tmp',
|
||||
getLocale: () => 'en'
|
||||
getVersion: () => "99.99.99",
|
||||
getPath: () => "tmp",
|
||||
getLocale: () => "en"
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -16,7 +16,7 @@ describe("workspace store tests", () => {
|
||||
describe("for an empty config", () => {
|
||||
beforeEach(async () => {
|
||||
WorkspaceStore.resetInstance();
|
||||
mockFs({ tmp: { 'lens-workspace-store.json': "{}" } });
|
||||
mockFs({ tmp: { "lens-workspace-store.json": "{}" } });
|
||||
|
||||
await WorkspaceStore.getInstance<WorkspaceStore>().load();
|
||||
});
|
||||
@@ -146,7 +146,7 @@ describe("workspace store tests", () => {
|
||||
WorkspaceStore.resetInstance();
|
||||
mockFs({
|
||||
tmp: {
|
||||
'lens-workspace-store.json': JSON.stringify({
|
||||
"lens-workspace-store.json": JSON.stringify({
|
||||
currentWorkspace: "abc",
|
||||
workspaces: [{
|
||||
id: "abc",
|
||||
|
||||
@@ -2,7 +2,7 @@ import path from "path";
|
||||
import Config from "conf";
|
||||
import { Options as ConfOptions } from "conf/dist/source/types";
|
||||
import { app, ipcMain, IpcMainEvent, ipcRenderer, IpcRendererEvent, remote } from "electron";
|
||||
import { action, IReactionOptions, observable, reaction, runInAction, toJS, when } from "mobx";
|
||||
import { IReactionOptions, observable, reaction, runInAction, when } from "mobx";
|
||||
import Singleton from "./utils/singleton";
|
||||
import { getAppVersion } from "./utils/app-version";
|
||||
import logger from "../main/logger";
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ export async function requestMain(channel: string, ...args: any[]) {
|
||||
|
||||
async function getSubFrames(): Promise<number[]> {
|
||||
const subFrames: number[] = [];
|
||||
clusterFrameMap.forEach((frameId, _) => {
|
||||
clusterFrameMap.forEach(frameId => {
|
||||
subFrames.push(frameId);
|
||||
});
|
||||
return subFrames;
|
||||
|
||||
+10
-10
@@ -7,7 +7,7 @@ import logger from "../main/logger";
|
||||
import commandExists from "command-exists";
|
||||
import { ExecValidationNotFoundError } from "./custom-errors";
|
||||
|
||||
export const kubeConfigDefaultPath = path.join(os.homedir(), '.kube', 'config');
|
||||
export const kubeConfigDefaultPath = path.join(os.homedir(), ".kube", "config");
|
||||
|
||||
function resolveTilde(filePath: string) {
|
||||
if (filePath[0] === "~" && (filePath[1] === "/" || filePath.length === 1)) {
|
||||
@@ -78,15 +78,15 @@ export function dumpConfigYaml(kubeConfig: Partial<KubeConfig>): string {
|
||||
apiVersion: "v1",
|
||||
kind: "Config",
|
||||
preferences: {},
|
||||
'current-context': kubeConfig.currentContext,
|
||||
"current-context": kubeConfig.currentContext,
|
||||
clusters: kubeConfig.clusters.map(cluster => {
|
||||
return {
|
||||
name: cluster.name,
|
||||
cluster: {
|
||||
'certificate-authority-data': cluster.caData,
|
||||
'certificate-authority': cluster.caFile,
|
||||
"certificate-authority-data": cluster.caData,
|
||||
"certificate-authority": cluster.caFile,
|
||||
server: cluster.server,
|
||||
'insecure-skip-tls-verify': cluster.skipTLSVerify
|
||||
"insecure-skip-tls-verify": cluster.skipTLSVerify
|
||||
}
|
||||
};
|
||||
}),
|
||||
@@ -104,11 +104,11 @@ export function dumpConfigYaml(kubeConfig: Partial<KubeConfig>): string {
|
||||
return {
|
||||
name: user.name,
|
||||
user: {
|
||||
'client-certificate-data': user.certData,
|
||||
'client-certificate': user.certFile,
|
||||
'client-key-data': user.keyData,
|
||||
'client-key': user.keyFile,
|
||||
'auth-provider': user.authProvider,
|
||||
"client-certificate-data": user.certData,
|
||||
"client-certificate": user.certFile,
|
||||
"client-key-data": user.keyData,
|
||||
"client-key": user.keyFile,
|
||||
"auth-provider": user.authProvider,
|
||||
exec: user.exec,
|
||||
token: user.token,
|
||||
username: user.username,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ThemeId } from "../renderer/theme.store";
|
||||
import { app, remote } from 'electron';
|
||||
import { app, remote } from "electron";
|
||||
import semver from "semver";
|
||||
import { readFile } from "fs-extra";
|
||||
import { action, observable, reaction, toJS } from "mobx";
|
||||
@@ -9,7 +9,7 @@ import { getAppVersion } from "./utils/app-version";
|
||||
import { kubeConfigDefaultPath, loadConfig } from "./kube-helpers";
|
||||
import { appEventBus } from "./event-bus";
|
||||
import logger from "../main/logger";
|
||||
import path from 'path';
|
||||
import path from "path";
|
||||
|
||||
export interface UserStoreModel {
|
||||
kubeConfigPath: string;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
export function debouncePromise<T, F extends any[]>(func: (...args: F) => T | Promise<T>, timeout = 0): (...args: F) => Promise<T> {
|
||||
let timer: NodeJS.Timeout;
|
||||
return (...params: any[]) => new Promise((resolve, reject) => {
|
||||
return (...params: any[]) => new Promise(resolve => {
|
||||
clearTimeout(timer);
|
||||
timer = global.setTimeout(() => resolve(func.apply(this, params)), timeout);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Helper to sanitize / escape special chars for passing to RegExp-constructor
|
||||
|
||||
export function escapeRegExp(str: string) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
|
||||
}
|
||||
@@ -8,7 +8,7 @@ jest.mock(
|
||||
"electron",
|
||||
() => ({
|
||||
ipcRenderer: {
|
||||
invoke: jest.fn(async (channel: string, ...args: any[]) => {
|
||||
invoke: jest.fn(async (channel: string) => {
|
||||
if (channel === "extensions:loaded") {
|
||||
return [
|
||||
[
|
||||
|
||||
@@ -112,7 +112,7 @@ export abstract class ClusterFeature {
|
||||
fs.readdirSync(folderPath).forEach(filename => {
|
||||
const file = path.join(folderPath, filename);
|
||||
const raw = fs.readFileSync(file);
|
||||
if (filename.endsWith('.hb')) {
|
||||
if (filename.endsWith(".hb")) {
|
||||
const template = hb.compile(raw.toString());
|
||||
resources.push(template(this.templateContext));
|
||||
} else {
|
||||
|
||||
@@ -162,7 +162,7 @@ export class ExtensionDiscovery {
|
||||
if (path.relative(this.localFolderPath, filePath) === extensionFolderName) {
|
||||
const extensionName: string | undefined = Object
|
||||
.entries(this.packagesJson.dependencies)
|
||||
.find(([_name, extensionFolder]) => filePath === extensionFolder)?.[0];
|
||||
.find(([, extensionFolder]) => filePath === extensionFolder)?.[0];
|
||||
|
||||
if (extensionName !== undefined) {
|
||||
delete this.packagesJson.dependencies[extensionName];
|
||||
@@ -244,7 +244,6 @@ export class ExtensionDiscovery {
|
||||
isBundled?: boolean;
|
||||
} = {}): Promise<InstalledExtension | null> {
|
||||
let manifestJson: LensExtensionManifest;
|
||||
let isEnabled: boolean;
|
||||
|
||||
try {
|
||||
// check manifest file for existence
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AwaitLock from 'await-lock';
|
||||
import AwaitLock from "await-lock";
|
||||
import child_process from "child_process";
|
||||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
@@ -27,7 +27,7 @@ export class ExtensionInstaller {
|
||||
}
|
||||
|
||||
get npmPath() {
|
||||
return __non_webpack_require__.resolve('npm/bin/npm-cli');
|
||||
return __non_webpack_require__.resolve("npm/bin/npm-cli");
|
||||
}
|
||||
|
||||
installDependencies(): Promise<void> {
|
||||
|
||||
@@ -21,13 +21,9 @@ export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> {
|
||||
|
||||
@computed
|
||||
get enabledExtensions() {
|
||||
const extensions: string[] = [];
|
||||
this.state.forEach((state, id) => {
|
||||
if (state.enabled) {
|
||||
extensions.push(state.name);
|
||||
}
|
||||
});
|
||||
return extensions;
|
||||
return Array.from(this.state.values())
|
||||
.filter(({enabled}) => enabled)
|
||||
.map(({name}) => name);
|
||||
}
|
||||
|
||||
protected state = observable.map<LensExtensionId, LensExtensionState>();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { MenuRegistration } from "./registries/menu-registry";
|
||||
import { observable } from "mobx";
|
||||
import { LensExtension } from "./lens-extension";
|
||||
import { WindowManager } from "../main/window-manager";
|
||||
import { getExtensionPageUrl } from "./registries/page-registry";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { AppPreferenceRegistration, ClusterFeatureRegistration, KubeObjectDetailRegistration, KubeObjectMenuRegistration, KubeObjectStatusRegistration, PageMenuRegistration, PageRegistration, StatusBarRegistration, } from "./registries";
|
||||
import type { Cluster } from "../main/cluster";
|
||||
import { observable } from "mobx";
|
||||
import { LensExtension } from "./lens-extension";
|
||||
import { getExtensionPageUrl } from "./registries/page-registry";
|
||||
|
||||
@@ -30,6 +29,7 @@ export class LensRendererExtension extends LensExtension {
|
||||
/**
|
||||
* Defines if extension is enabled for a given cluster. Defaults to `true`.
|
||||
*/
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars-ts
|
||||
async isEnabledForCluster(cluster: Cluster): Promise<Boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getExtensionPageUrl, globalPageRegistry, PageRegistration } from "../page-registry";
|
||||
import { getExtensionPageUrl, globalPageRegistry } from "../page-registry";
|
||||
import { LensExtension } from "../../lens-extension";
|
||||
import React from "react";
|
||||
|
||||
@@ -53,18 +53,18 @@ describe("globalPageRegistry", () => {
|
||||
{
|
||||
id: "test-page",
|
||||
components: {
|
||||
Page: () => React.createElement('Text')
|
||||
Page: () => React.createElement("Text")
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "another-page",
|
||||
components: {
|
||||
Page: () => React.createElement('Text')
|
||||
Page: () => React.createElement("Text")
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Page: () => React.createElement('Default')
|
||||
Page: () => React.createElement("Default")
|
||||
}
|
||||
},
|
||||
], ext);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Extensions-api -> Register page menu items
|
||||
import type { IconProps } from "../../renderer/components/icon";
|
||||
import type React from "react";
|
||||
import { action, computed } from "mobx";
|
||||
import { action } from "mobx";
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
import { LensExtension } from "../lens-extension";
|
||||
import { RegisteredPage } from "./page-registry";
|
||||
|
||||
@@ -146,7 +146,7 @@ describe("create clusters", () => {
|
||||
}
|
||||
}));
|
||||
|
||||
mockedRequest.mockImplementationOnce(((uri: any, _options: any) => {
|
||||
mockedRequest.mockImplementationOnce(((uri: any) => {
|
||||
expect(uri).toBe(`http://localhost:${port}/api-kube/version`);
|
||||
return Promise.resolve({ gitVersion: "1.2.3" });
|
||||
}) as any);
|
||||
|
||||
@@ -31,10 +31,10 @@ import { Cluster } from "../cluster";
|
||||
import { KubeAuthProxy } from "../kube-auth-proxy";
|
||||
import { getFreePort } from "../port";
|
||||
import { broadcastMessage } from "../../common/ipc";
|
||||
import { ChildProcess, spawn, SpawnOptions } from "child_process";
|
||||
import { ChildProcess, spawn } from "child_process";
|
||||
import { bundledKubectlPath, Kubectl } from "../kubectl";
|
||||
import { mock, MockProxy } from 'jest-mock-extended';
|
||||
import { waitUntilUsed } from 'tcp-port-used';
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { waitUntilUsed } from "tcp-port-used";
|
||||
import { Readable } from "stream";
|
||||
|
||||
const mockBroadcastIpc = broadcastMessage as jest.MockedFunction<typeof broadcastMessage>;
|
||||
@@ -81,7 +81,7 @@ describe("kube auth proxy tests", () => {
|
||||
listeners[`stdout/${event}`] = listener;
|
||||
return mockedCP.stdout;
|
||||
});
|
||||
mockSpawn.mockImplementationOnce((command: string, args: readonly string[], options: SpawnOptions): ChildProcess => {
|
||||
mockSpawn.mockImplementationOnce((command: string): ChildProcess => {
|
||||
expect(command).toBe(bundledKubectlPath());
|
||||
return mockedCP;
|
||||
});
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { ContextHandler } from "./context-handler";
|
||||
import { AuthorizationV1Api, CoreV1Api, KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node";
|
||||
import { Kubectl } from "./kubectl";
|
||||
import { KubeconfigManager } from "./kubeconfig-manager";
|
||||
import { getNodeWarningConditions, loadConfig, podHasIssues } from "../common/kube-helpers";
|
||||
import { loadConfig } from "../common/kube-helpers";
|
||||
import request, { RequestPromiseOptions } from "request-promise-native";
|
||||
import { apiResources } from "../common/rbac";
|
||||
import logger from "./logger";
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* The dependency is not bundled to the production build.
|
||||
*/
|
||||
export const installDeveloperTools = async () => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const { default: devToolsInstaller, REACT_DEVELOPER_TOOLS } = await import('electron-devtools-installer');
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
const { default: devToolsInstaller, REACT_DEVELOPER_TOOLS } = await import("electron-devtools-installer");
|
||||
|
||||
return devToolsInstaller([REACT_DEVELOPER_TOOLS]);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export function exitApp() {
|
||||
appEventBus.emit({ name: "service", action: "close" });
|
||||
windowManager.hide();
|
||||
clusterManager.stop();
|
||||
logger.info('SERVICE:QUIT');
|
||||
logger.info("SERVICE:QUIT");
|
||||
setTimeout(() => {
|
||||
app.exit();
|
||||
}, 1000);
|
||||
|
||||
@@ -36,10 +36,10 @@ export class HelmChartManager {
|
||||
public async getReadme(name: string, version = "") {
|
||||
const helm = await helmCli.binaryPath();
|
||||
if(version && version != "") {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
} else {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
}
|
||||
}
|
||||
@@ -47,11 +47,11 @@ export class HelmChartManager {
|
||||
public async getValues(name: string, version = "") {
|
||||
const helm = await helmCli.binaryPath();
|
||||
if(version && version != "") {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show values ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
|
||||
return stdout;
|
||||
} else {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
|
||||
return stdout;
|
||||
}
|
||||
@@ -59,12 +59,12 @@ export class HelmChartManager {
|
||||
|
||||
protected async cachedYaml(): Promise<CachedYaml> {
|
||||
if (!(this.repo.name in this.cache)) {
|
||||
const cacheFile = await fs.promises.readFile(this.repo.cacheFilePath, 'utf-8');
|
||||
const cacheFile = await fs.promises.readFile(this.repo.cacheFilePath, "utf-8");
|
||||
const data = yaml.safeLoad(cacheFile);
|
||||
for(const key in data["entries"]) {
|
||||
data["entries"][key].forEach((version: any) => {
|
||||
version['repo'] = this.repo.name;
|
||||
version['created'] = Date.parse(version.created).toString();
|
||||
version["repo"] = this.repo.name;
|
||||
version["created"] = Date.parse(version.created).toString();
|
||||
});
|
||||
}
|
||||
this.cache[this.repo.name] = Buffer.from(JSON.stringify(data));
|
||||
|
||||
@@ -34,8 +34,8 @@ export class HelmReleaseManager {
|
||||
generateName = "--generate-name";
|
||||
name = "";
|
||||
}
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" install ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} ${generateName}`).catch((error) => { throw(error.stderr);});
|
||||
const releaseName = stdout.split("\n")[0].split(' ')[1].trim();
|
||||
const { stdout } = await promiseExec(`"${helm}" install ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} ${generateName}`).catch((error) => { throw(error.stderr);});
|
||||
const releaseName = stdout.split("\n")[0].split(" ")[1].trim();
|
||||
return {
|
||||
log: stdout,
|
||||
release: {
|
||||
@@ -54,7 +54,7 @@ export class HelmReleaseManager {
|
||||
await fs.promises.writeFile(fileName, yaml.safeDump(values));
|
||||
|
||||
try {
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" upgrade ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" upgrade ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
return {
|
||||
log: stdout,
|
||||
release: this.getRelease(name, namespace, cluster)
|
||||
@@ -66,7 +66,7 @@ export class HelmReleaseManager {
|
||||
|
||||
public async getRelease(name: string, namespace: string, cluster: Cluster) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const {stdout, stderr} = await promiseExec(`"${helm}" status ${name} --output json --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" status ${name} --output json --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
const release = JSON.parse(stdout);
|
||||
release.resources = await this.getResources(name, namespace, cluster);
|
||||
return release;
|
||||
@@ -74,26 +74,26 @@ export class HelmReleaseManager {
|
||||
|
||||
public async deleteRelease(name: string, namespace: string, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" delete ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" delete ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public async getValues(name: string, namespace: string, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" get values ${name} --all --output yaml --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout, } = await promiseExec(`"${helm}" get values ${name} --all --output yaml --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public async getHistory(name: string, namespace: string, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const {stdout, stderr} = await promiseExec(`"${helm}" history ${name} --output json --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" history ${name} --output json --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
public async rollback(name: string, namespace: string, revision: number, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const {stdout, stderr} = await promiseExec(`"${helm}" rollback ${name} ${revision} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" rollback ${name} ${revision} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class HelmReleaseManager {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const kubectl = await cluster.kubeCtl.getPath();
|
||||
const pathToKubeconfig = cluster.getProxyKubeconfigPath();
|
||||
const { stdout } = await promiseExec(`"${helm}" get manifest ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} | "${kubectl}" get -n ${namespace} --kubeconfig ${pathToKubeconfig} -f - -o=json`).catch((error) => {
|
||||
const { stdout } = await promiseExec(`"${helm}" get manifest ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} | "${kubectl}" get -n ${namespace} --kubeconfig ${pathToKubeconfig} -f - -o=json`).catch(() => {
|
||||
return { stdout: JSON.stringify({items: []})};
|
||||
});
|
||||
return stdout;
|
||||
|
||||
@@ -77,7 +77,7 @@ export class HelmRepoManager extends Singleton {
|
||||
}
|
||||
try {
|
||||
const repoConfigFile = this.helmEnv.HELM_REPOSITORY_CONFIG;
|
||||
const { repositories }: HelmRepoConfig = await readFile(repoConfigFile, 'utf8')
|
||||
const { repositories }: HelmRepoConfig = await readFile(repoConfigFile, "utf8")
|
||||
.then((yamlContent: string) => yaml.safeLoad(yamlContent))
|
||||
.catch(() => ({
|
||||
repositories: []
|
||||
@@ -121,7 +121,7 @@ export class HelmRepoManager extends Singleton {
|
||||
public async removeRepo({ name, url }: HelmRepo): Promise<string> {
|
||||
logger.info(`[HELM]: removing repo "${name}" from ${url}`);
|
||||
const helm = await helmCli.binaryPath();
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" repo remove ${name}`).catch((error) => {
|
||||
const { stdout } = await promiseExec(`"${helm}" repo remove ${name}`).catch((error) => {
|
||||
throw(error.stderr);
|
||||
});
|
||||
return stdout;
|
||||
|
||||
@@ -85,7 +85,7 @@ class HelmService {
|
||||
for (const key in entries) {
|
||||
entries[key] = entries[key].filter((entry: any) => {
|
||||
if (Array.isArray(entry)) {
|
||||
return entry[0]['deprecated'] != true;
|
||||
return entry[0]["deprecated"] != true;
|
||||
}
|
||||
return entry["deprecated"] != true;
|
||||
});
|
||||
|
||||
+3
-2
@@ -77,6 +77,7 @@ app.on("ready", async () => {
|
||||
|
||||
// run proxy
|
||||
try {
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars-ts
|
||||
proxyServer = LensProxy.create(proxyPort, clusterManager);
|
||||
} catch (error) {
|
||||
logger.error(`Could not start proxy (127.0.0:${proxyPort}): ${error.message}`);
|
||||
@@ -108,7 +109,7 @@ app.on("ready", async () => {
|
||||
});
|
||||
|
||||
app.on("activate", (event, hasVisibleWindows) => {
|
||||
logger.info('APP:ACTIVATE', { hasVisibleWindows });
|
||||
logger.info("APP:ACTIVATE", { hasVisibleWindows });
|
||||
if (!hasVisibleWindows) {
|
||||
windowManager.initMainWindow();
|
||||
}
|
||||
@@ -116,7 +117,7 @@ app.on("activate", (event, hasVisibleWindows) => {
|
||||
|
||||
// Quit app on Cmd+Q (MacOS)
|
||||
app.on("will-quit", (event) => {
|
||||
logger.info('APP:QUIT');
|
||||
logger.info("APP:QUIT");
|
||||
appEventBus.emit({name: "app", action: "close"});
|
||||
event.preventDefault(); // prevent app's default shutdown (e.g. required for telemetry, etc.)
|
||||
clusterManager?.stop(); // close cluster connections
|
||||
|
||||
@@ -60,7 +60,7 @@ export class KubeAuthProxy {
|
||||
this.exit();
|
||||
});
|
||||
|
||||
this.proxyProcess.stdout.on('data', (data) => {
|
||||
this.proxyProcess.stdout.on("data", (data) => {
|
||||
let logItem = data.toString();
|
||||
if (logItem.startsWith("Starting to serve on")) {
|
||||
logItem = "Authentication proxy started\n";
|
||||
@@ -68,7 +68,7 @@ export class KubeAuthProxy {
|
||||
this.sendIpcLogMessage({ data: logItem });
|
||||
});
|
||||
|
||||
this.proxyProcess.stderr.on('data', (data) => {
|
||||
this.proxyProcess.stderr.on("data", (data) => {
|
||||
this.lastError = this.parseError(data.toString());
|
||||
this.sendIpcLogMessage({ data: data.toString(), error: true });
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@ export class KubeconfigManager {
|
||||
* This way any user of the config does not need to know anything about the auth etc. details.
|
||||
*/
|
||||
protected async createProxyKubeconfig(): Promise<string> {
|
||||
const { configDir, cluster, contextHandler } = this;
|
||||
const { configDir, cluster } = this;
|
||||
const { contextName, kubeConfigPath, id } = cluster;
|
||||
const tempFile = path.join(configDir, `kubeconfig-${id}`);
|
||||
const kubeConfig = loadConfig(kubeConfigPath);
|
||||
@@ -81,7 +81,7 @@ export class KubeconfigManager {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('Deleting temporary kubeconfig: ' + this.tempFile);
|
||||
logger.info("Deleting temporary kubeconfig: " + this.tempFile);
|
||||
await fs.unlink(this.tempFile);
|
||||
this.tempFile = undefined;
|
||||
}
|
||||
|
||||
+7
-3
@@ -123,6 +123,10 @@ export class Kubectl {
|
||||
}
|
||||
|
||||
public async getPath(bundled = false): Promise<string> {
|
||||
if (bundled) {
|
||||
return this.getBundledPath();
|
||||
}
|
||||
|
||||
if (userStore.preferences?.downloadKubectlBinaries === false) {
|
||||
return this.getPathFromPreferences();
|
||||
}
|
||||
@@ -167,7 +171,7 @@ export class Kubectl {
|
||||
return true;
|
||||
}
|
||||
let version: string = output.clientVersion.gitVersion;
|
||||
if (version[0] === 'v') {
|
||||
if (version[0] === "v") {
|
||||
version = version.slice(1);
|
||||
}
|
||||
if (version === this.kubectlVersion) {
|
||||
@@ -274,7 +278,7 @@ export class Kubectl {
|
||||
const kubectlPath = userStore.preferences?.downloadKubectlBinaries ? this.dirname : path.dirname(this.getPathFromPreferences());
|
||||
const helmPath = helmCli.getBinaryDir();
|
||||
const fsPromises = fs.promises;
|
||||
const bashScriptPath = path.join(this.dirname, '.bash_set_path');
|
||||
const bashScriptPath = path.join(this.dirname, ".bash_set_path");
|
||||
|
||||
let bashScript = "" + initScriptVersionString;
|
||||
bashScript += "tempkubeconfig=\"$KUBECONFIG\"\n";
|
||||
@@ -297,7 +301,7 @@ export class Kubectl {
|
||||
bashScript += "unset tempkubeconfig\n";
|
||||
await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 });
|
||||
|
||||
const zshScriptPath = path.join(this.dirname, '.zlogin');
|
||||
const zshScriptPath = path.join(this.dirname, ".zlogin");
|
||||
|
||||
let zshScript = "" + initScriptVersionString;
|
||||
|
||||
|
||||
@@ -121,12 +121,12 @@ export class LensBinary {
|
||||
}
|
||||
|
||||
protected async untarBinary() {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
return new Promise<void>(resolve => {
|
||||
this.logger.debug(`Extracting ${this.originalBinaryName} binary`);
|
||||
tar.x({
|
||||
file: this.tarPath,
|
||||
cwd: this.dirname
|
||||
}).then((_ => {
|
||||
}).then((() => {
|
||||
resolve();
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -88,23 +88,23 @@ export class LensProxy {
|
||||
proxySocket.setTimeout(0);
|
||||
socket.setTimeout(0);
|
||||
|
||||
proxySocket.on('data', function (chunk) {
|
||||
proxySocket.on("data", function (chunk) {
|
||||
socket.write(chunk);
|
||||
});
|
||||
proxySocket.on('end', function () {
|
||||
proxySocket.on("end", function () {
|
||||
socket.end();
|
||||
});
|
||||
proxySocket.on('error', function (err) {
|
||||
proxySocket.on("error", function () {
|
||||
socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
|
||||
socket.end();
|
||||
});
|
||||
socket.on('data', function (chunk) {
|
||||
socket.on("data", function (chunk) {
|
||||
proxySocket.write(chunk);
|
||||
});
|
||||
socket.on('end', function () {
|
||||
socket.on("end", function () {
|
||||
proxySocket.end();
|
||||
});
|
||||
socket.on('error', function () {
|
||||
socket.on("error", function () {
|
||||
proxySocket.end();
|
||||
});
|
||||
}
|
||||
|
||||
+55
-55
@@ -65,31 +65,31 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
showAbout(browserWindow);
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'CmdOrCtrl+,',
|
||||
label: "Preferences",
|
||||
accelerator: "CmdOrCtrl+,",
|
||||
click() {
|
||||
navigate(preferencesURL());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Extensions',
|
||||
accelerator: 'CmdOrCtrl+Shift+E',
|
||||
label: "Extensions",
|
||||
accelerator: "CmdOrCtrl+Shift+E",
|
||||
click() {
|
||||
navigate(extensionsURL());
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{ role: "services" },
|
||||
{ type: "separator" },
|
||||
{ role: "hide" },
|
||||
{ role: "hideOthers" },
|
||||
{ role: "unhide" },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Cmd+Q',
|
||||
label: "Quit",
|
||||
accelerator: "Cmd+Q",
|
||||
click() {
|
||||
exitApp();
|
||||
}
|
||||
@@ -101,16 +101,16 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
label: "File",
|
||||
submenu: [
|
||||
{
|
||||
label: 'Add Cluster',
|
||||
accelerator: 'CmdOrCtrl+Shift+A',
|
||||
label: "Add Cluster",
|
||||
accelerator: "CmdOrCtrl+Shift+A",
|
||||
click() {
|
||||
navigate(addClusterURL());
|
||||
}
|
||||
},
|
||||
...activeClusterOnly([
|
||||
{
|
||||
label: 'Cluster Settings',
|
||||
accelerator: 'CmdOrCtrl+Shift+S',
|
||||
label: "Cluster Settings",
|
||||
accelerator: "CmdOrCtrl+Shift+S",
|
||||
click() {
|
||||
navigate(clusterSettingsURL({
|
||||
params: {
|
||||
@@ -121,32 +121,32 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
}
|
||||
]),
|
||||
...ignoreOnMac([
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'Ctrl+,',
|
||||
label: "Preferences",
|
||||
accelerator: "Ctrl+,",
|
||||
click() {
|
||||
navigate(preferencesURL());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Extensions',
|
||||
accelerator: 'Ctrl+Shift+E',
|
||||
label: "Extensions",
|
||||
accelerator: "Ctrl+Shift+E",
|
||||
click() {
|
||||
navigate(extensionsURL());
|
||||
}
|
||||
}
|
||||
]),
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
role: 'close',
|
||||
role: "close",
|
||||
label: "Close Window"
|
||||
},
|
||||
...ignoreOnMac([
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Exit',
|
||||
accelerator: 'Alt+F4',
|
||||
label: "Exit",
|
||||
accelerator: "Alt+F4",
|
||||
click() {
|
||||
exitApp();
|
||||
}
|
||||
@@ -156,56 +156,56 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
};
|
||||
|
||||
const editMenu: MenuItemConstructorOptions = {
|
||||
label: 'Edit',
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
{ role: 'delete' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'selectAll' },
|
||||
{ role: "undo" },
|
||||
{ role: "redo" },
|
||||
{ type: "separator" },
|
||||
{ role: "cut" },
|
||||
{ role: "copy" },
|
||||
{ role: "paste" },
|
||||
{ role: "delete" },
|
||||
{ type: "separator" },
|
||||
{ role: "selectAll" },
|
||||
]
|
||||
};
|
||||
|
||||
const viewMenu: MenuItemConstructorOptions = {
|
||||
label: 'View',
|
||||
label: "View",
|
||||
submenu: [
|
||||
{
|
||||
label: 'Back',
|
||||
accelerator: 'CmdOrCtrl+[',
|
||||
label: "Back",
|
||||
accelerator: "CmdOrCtrl+[",
|
||||
click() {
|
||||
webContents.getFocusedWebContents()?.goBack();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Forward',
|
||||
accelerator: 'CmdOrCtrl+]',
|
||||
label: "Forward",
|
||||
accelerator: "CmdOrCtrl+]",
|
||||
click() {
|
||||
webContents.getFocusedWebContents()?.goForward();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
label: "Reload",
|
||||
accelerator: "CmdOrCtrl+R",
|
||||
click() {
|
||||
windowManager.reload();
|
||||
}
|
||||
},
|
||||
{ role: 'toggleDevTools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' },
|
||||
{ role: 'zoomIn' },
|
||||
{ role: 'zoomOut' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' }
|
||||
{ role: "toggleDevTools" },
|
||||
{ type: "separator" },
|
||||
{ role: "resetZoom" },
|
||||
{ role: "zoomIn" },
|
||||
{ role: "zoomOut" },
|
||||
{ type: "separator" },
|
||||
{ role: "togglefullscreen" }
|
||||
]
|
||||
};
|
||||
|
||||
const helpMenu: MenuItemConstructorOptions = {
|
||||
role: 'help',
|
||||
role: "help",
|
||||
submenu: [
|
||||
{
|
||||
label: "What's new?",
|
||||
@@ -265,7 +265,7 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
if (isTestEnv) {
|
||||
// this is a workaround for the test environment (spectron) not being able to directly access
|
||||
// the application menus (https://github.com/electron-userland/spectron/issues/21)
|
||||
ipcMain.on('test-menu-item-click', (event: IpcMainEvent, ...names: string[]) => {
|
||||
ipcMain.on("test-menu-item-click", (event: IpcMainEvent, ...names: string[]) => {
|
||||
let menu: Menu = Menu.getApplicationMenu();
|
||||
const parentLabels: string[] = [];
|
||||
let menuItem: MenuItem;
|
||||
@@ -286,7 +286,7 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
}
|
||||
|
||||
const { enabled, visible, click } = menuItem;
|
||||
if (enabled === false || visible === false || typeof click !== 'function') {
|
||||
if (enabled === false || visible === false || typeof click !== "function") {
|
||||
logger.info(`[MENU:test-menu-item-click] Menu item ${menuPath} not clickable`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export class NodeShellSession extends ShellSession {
|
||||
const shell = await this.kubectl.getPath();
|
||||
let args = [];
|
||||
if (this.createNodeShellPod(this.podId, this.nodeName)) {
|
||||
await this.waitForRunningPod(this.podId).catch((error) => {
|
||||
await this.waitForRunningPod(this.podId).catch(() => {
|
||||
this.exit(1001);
|
||||
});
|
||||
}
|
||||
@@ -108,7 +108,7 @@ export class NodeShellSession extends ShellSession {
|
||||
|
||||
const req = await watch.watch(`/api/v1/namespaces/kube-system/pods`, {},
|
||||
// callback is called for each received object.
|
||||
(_type, obj) => {
|
||||
(type, obj) => {
|
||||
if (obj.metadata.name == podId && obj.status.phase === "Running") {
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { EventEmitter } from "events";
|
||||
import { getFreePort } from "./port";
|
||||
|
||||
let newPort = 0;
|
||||
@@ -8,7 +8,7 @@ jest.mock("net", () => {
|
||||
createServer() {
|
||||
return new class MockServer extends EventEmitter {
|
||||
listen = jest.fn(() => {
|
||||
this.emit('listening');
|
||||
this.emit("listening");
|
||||
return this;
|
||||
});
|
||||
address = () => {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
|
||||
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||
switch(opts.category) {
|
||||
case 'cluster':
|
||||
case "cluster":
|
||||
return {
|
||||
memoryUsage: `
|
||||
sum(
|
||||
@@ -43,7 +43,7 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`
|
||||
};
|
||||
case 'nodes':
|
||||
case "nodes":
|
||||
return {
|
||||
memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_node)`,
|
||||
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||
@@ -52,7 +52,7 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (kubernetes_node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (kubernetes_node)`
|
||||
};
|
||||
case 'pods':
|
||||
case "pods":
|
||||
return {
|
||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||
@@ -64,12 +64,12 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||
};
|
||||
case 'pvc':
|
||||
case "pvc":
|
||||
return {
|
||||
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||
};
|
||||
case 'ingress':
|
||||
case "ingress":
|
||||
const bytesSent = (ingress: string, statuses: string) =>
|
||||
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
|
||||
return {
|
||||
|
||||
@@ -32,7 +32,7 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
|
||||
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||
switch(opts.category) {
|
||||
case 'cluster':
|
||||
case "cluster":
|
||||
return {
|
||||
memoryUsage: `
|
||||
sum(
|
||||
@@ -51,7 +51,7 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"} - node_filesystem_avail_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`
|
||||
};
|
||||
case 'nodes':
|
||||
case "nodes":
|
||||
return {
|
||||
memoryUsage: `sum((node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
|
||||
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||
@@ -60,7 +60,7 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
|
||||
fsUsage: `sum((node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`
|
||||
};
|
||||
case 'pods':
|
||||
case "pods":
|
||||
return {
|
||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||
@@ -72,12 +72,12 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||
};
|
||||
case 'pvc':
|
||||
case "pvc":
|
||||
return {
|
||||
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||
};
|
||||
case 'ingress':
|
||||
case "ingress":
|
||||
const bytesSent = (ingress: string, statuses: string) =>
|
||||
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
|
||||
return {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
|
||||
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||
switch(opts.category) {
|
||||
case 'cluster':
|
||||
case "cluster":
|
||||
return {
|
||||
memoryUsage: `
|
||||
sum(
|
||||
@@ -43,7 +43,7 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`
|
||||
};
|
||||
case 'nodes':
|
||||
case "nodes":
|
||||
return {
|
||||
memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (node)`,
|
||||
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||
@@ -52,7 +52,7 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (node)`
|
||||
};
|
||||
case 'pods':
|
||||
case "pods":
|
||||
return {
|
||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||
@@ -64,12 +64,12 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||
};
|
||||
case 'pvc':
|
||||
case "pvc":
|
||||
return {
|
||||
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||
};
|
||||
case 'ingress':
|
||||
case "ingress":
|
||||
const bytesSent = (ingress: string, statuses: string) =>
|
||||
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
|
||||
return {
|
||||
|
||||
@@ -75,7 +75,7 @@ export class ResourceApplier {
|
||||
delete resource.metadata?.resourceVersion;
|
||||
const annotations = resource.metadata?.annotations;
|
||||
if (annotations) {
|
||||
delete annotations['kubectl.kubernetes.io/last-applied-configuration'];
|
||||
delete annotations["kubectl.kubernetes.io/last-applied-configuration"];
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
+4
-4
@@ -100,11 +100,11 @@ export class Router {
|
||||
try {
|
||||
const filename = path.basename(req.url);
|
||||
// redirect requests to [appName].js, [appName].html /sockjs-node/ to webpack-dev-server (for hot-reload support)
|
||||
const toWebpackDevServer = filename.includes(appName) || filename.includes('hot-update') || req.url.includes('sockjs-node');
|
||||
const toWebpackDevServer = filename.includes(appName) || filename.includes("hot-update") || req.url.includes("sockjs-node");
|
||||
if (isDevelopment && toWebpackDevServer) {
|
||||
const redirectLocation = `http://localhost:${webpackDevServerPort}` + req.url;
|
||||
res.statusCode = 307;
|
||||
res.setHeader('Location', redirectLocation);
|
||||
res.setHeader("Location", redirectLocation);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
@@ -126,8 +126,8 @@ export class Router {
|
||||
protected addRoutes() {
|
||||
// Static assets
|
||||
this.router.add(
|
||||
{ method: 'get', path: '/{path*}' },
|
||||
({ params, response, path, raw: { req } }: LensApiRequest) => {
|
||||
{ method: "get", path: "/{path*}" },
|
||||
({ params, response, raw: { req } }: LensApiRequest) => {
|
||||
this.handleStaticFile(params.path, response, req);
|
||||
});
|
||||
|
||||
|
||||
@@ -6,36 +6,36 @@ import { CoreV1Api, V1Secret } from "@kubernetes/client-node";
|
||||
function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster) {
|
||||
const tokenData = Buffer.from(secret.data["token"], "base64");
|
||||
return {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'Config',
|
||||
'clusters': [
|
||||
"apiVersion": "v1",
|
||||
"kind": "Config",
|
||||
"clusters": [
|
||||
{
|
||||
'name': cluster.contextName,
|
||||
'cluster': {
|
||||
'server': cluster.apiUrl,
|
||||
'certificate-authority-data': secret.data["ca.crt"]
|
||||
"name": cluster.contextName,
|
||||
"cluster": {
|
||||
"server": cluster.apiUrl,
|
||||
"certificate-authority-data": secret.data["ca.crt"]
|
||||
}
|
||||
}
|
||||
],
|
||||
'users': [
|
||||
"users": [
|
||||
{
|
||||
'name': username,
|
||||
'user': {
|
||||
'token': tokenData.toString("utf8"),
|
||||
"name": username,
|
||||
"user": {
|
||||
"token": tokenData.toString("utf8"),
|
||||
}
|
||||
}
|
||||
],
|
||||
'contexts': [
|
||||
"contexts": [
|
||||
{
|
||||
'name': cluster.contextName,
|
||||
'context': {
|
||||
'user': username,
|
||||
'cluster': cluster.contextName,
|
||||
'namespace': secret.metadata.namespace,
|
||||
"name": cluster.contextName,
|
||||
"context": {
|
||||
"user": username,
|
||||
"cluster": cluster.contextName,
|
||||
"namespace": secret.metadata.namespace,
|
||||
}
|
||||
}
|
||||
],
|
||||
'current-context': cluster.contextName
|
||||
"current-context": cluster.contextName
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class ApiWatcher {
|
||||
class WatchRoute extends LensApi {
|
||||
|
||||
public async routeWatch(request: LensApiRequest) {
|
||||
const { params, response, cluster} = request;
|
||||
const { response, cluster} = request;
|
||||
const apis: string[] = request.query.getAll("api");
|
||||
const watchers: ApiWatcher[] = [];
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ export class ShellSession extends EventEmitter {
|
||||
case "powershell.exe":
|
||||
return ["-NoExit", "-command", `& {Set-Location $Env:USERPROFILE; $Env:PATH="${this.helmBinDir};${this.kubectlPathDir};$Env:PATH"}`];
|
||||
case "bash":
|
||||
return ["--init-file", path.join(this.kubectlBinDir, '.bash_set_path')];
|
||||
return ["--init-file", path.join(this.kubectlBinDir, ".bash_set_path")];
|
||||
case "fish":
|
||||
return ["--login", "--init-command", `export PATH="${this.helmBinDir}:${this.kubectlPathDir}:$PATH"; export KUBECONFIG="${this.kubeconfigPath}"`];
|
||||
case "zsh":
|
||||
@@ -156,7 +156,7 @@ export class ShellSession extends EventEmitter {
|
||||
this.shellProcess.resize(resizeMsgObj["Width"], resizeMsgObj["Height"]);
|
||||
break;
|
||||
case "9":
|
||||
this.emit('newToken', message);
|
||||
this.emit("newToken", message);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -164,7 +164,7 @@ export class ShellSession extends EventEmitter {
|
||||
|
||||
protected exit(code = 1000) {
|
||||
if (this.websocket.readyState == this.websocket.OPEN) this.websocket.close(code);
|
||||
this.emit('exit');
|
||||
this.emit("exit");
|
||||
}
|
||||
|
||||
protected closeWebsocketOnProcessExit() {
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function shellSync() {
|
||||
const env: Env = JSON.parse(JSON.stringify(envVars));
|
||||
if (!env.LANG) {
|
||||
// the LANG env var expects an underscore instead of electron's dash
|
||||
env.LANG = `${app.getLocale().replace('-', '_')}.UTF-8`;
|
||||
env.LANG = `${app.getLocale().replace("-", "_")}.UTF-8`;
|
||||
} else if (!env.LANG.endsWith(".UTF-8")) {
|
||||
env.LANG += ".UTF-8";
|
||||
}
|
||||
|
||||
+4
-4
@@ -66,7 +66,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
showAbout(browserWindow);
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "Open Lens",
|
||||
async click() {
|
||||
@@ -91,7 +91,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
submenu: clusters.map(cluster => {
|
||||
const { id: clusterId, name: label, online, workspace } = cluster;
|
||||
return {
|
||||
label: `${online ? '✓' : '\x20'.repeat(3)/*offset*/}${label}`,
|
||||
label: `${online ? "✓" : "\x20".repeat(3)/*offset*/}${label}`,
|
||||
toolTip: clusterId,
|
||||
async click() {
|
||||
workspaceStore.setActive(workspace);
|
||||
@@ -115,9 +115,9 @@ export function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
}
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Quit App',
|
||||
label: "Quit App",
|
||||
click() {
|
||||
exitApp();
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import { migration } from "../migration-wrapper";
|
||||
|
||||
export default migration({
|
||||
version: "2.0.0-beta.2",
|
||||
run(store, log) {
|
||||
run(store) {
|
||||
for (const value of store) {
|
||||
const contextName = value[0];
|
||||
// Looping all the keys gives out the store internal stuff too...
|
||||
if (contextName === "__internal__" || value[1].hasOwnProperty('kubeConfig')) continue;
|
||||
if (contextName === "__internal__" || value[1].hasOwnProperty("kubeConfig")) continue;
|
||||
store.set(contextName, { kubeConfig: value[1] });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { migration } from "../migration-wrapper";
|
||||
|
||||
export default migration({
|
||||
version: "2.4.1",
|
||||
run(store, log) {
|
||||
run(store) {
|
||||
for (const value of store) {
|
||||
const contextName = value[0];
|
||||
if (contextName === "__internal__") continue;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { migration } from "../migration-wrapper";
|
||||
|
||||
export default migration({
|
||||
version: "2.6.0-beta.2",
|
||||
run(store, log) {
|
||||
run(store) {
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
if (clusterKey === "__internal__") continue;
|
||||
|
||||
@@ -10,7 +10,7 @@ export default migration({
|
||||
const cluster = value[1];
|
||||
if (!cluster.kubeConfig) continue;
|
||||
const kubeConfig = yaml.safeLoad(cluster.kubeConfig);
|
||||
if (!kubeConfig.hasOwnProperty('users')) continue;
|
||||
if (!kubeConfig.hasOwnProperty("users")) continue;
|
||||
const userObj = kubeConfig.users[0];
|
||||
if (userObj) {
|
||||
const user = userObj.user;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { migration } from "../migration-wrapper";
|
||||
|
||||
export default migration({
|
||||
version: "2.7.0-beta.0",
|
||||
run(store, log) {
|
||||
run(store) {
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
if (clusterKey === "__internal__") continue;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { v4 as uuid } from "uuid";
|
||||
|
||||
export default migration({
|
||||
version: "2.7.0-beta.1",
|
||||
run(store, log) {
|
||||
run(store) {
|
||||
const clusters: any[] = [];
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
|
||||
@@ -44,7 +44,7 @@ export default migration({
|
||||
const iconPath = cluster.preferences.icon.replace("store://", "");
|
||||
const fileData = fse.readFileSync(path.join(userDataPath, iconPath));
|
||||
|
||||
cluster.preferences.icon = `data:;base64,${fileData.toString('base64')}`;
|
||||
cluster.preferences.icon = `data:;base64,${fileData.toString("base64")}`;
|
||||
} else {
|
||||
delete cluster.preferences?.icon;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Fix embedded kubeconfig paths under snap config
|
||||
|
||||
import { migration } from "../migration-wrapper";
|
||||
import { ClusterModel, ClusterStore } from "../../common/cluster-store";
|
||||
import { ClusterModel } from "../../common/cluster-store";
|
||||
import { getAppVersion } from "../../common/utils/app-version";
|
||||
import fs from "fs";
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export class ApiManager {
|
||||
return this.apis.get(pathOrCallback) || this.apis.get(KubeApi.parseApi(pathOrCallback).apiBase);
|
||||
}
|
||||
|
||||
return Array.from(this.apis.values()).find(pathOrCallback ?? ((api: KubeApi) => true));
|
||||
return Array.from(this.apis.values()).find(pathOrCallback ?? (() => true));
|
||||
}
|
||||
|
||||
registerApi(apiBase: string, api: KubeApi) {
|
||||
|
||||
@@ -40,7 +40,7 @@ export class DeploymentApi extends KubeApi<Deployment> {
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'content-type': 'application/strategic-merge-patch+json'
|
||||
"content-type": "application/strategic-merge-patch+json"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export const metricsApi = {
|
||||
|
||||
if (!start && !end) {
|
||||
const timeNow = Date.now() / 1000;
|
||||
const now = moment.unix(timeNow).startOf('minute').unix(); // round date to minutes
|
||||
const now = moment.unix(timeNow).startOf("minute").unix(); // round date to minutes
|
||||
start = now - range;
|
||||
end = now;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import { KubeApi } from "../kube-api";
|
||||
export class PersistentVolumeClaimsApi extends KubeApi<PersistentVolumeClaim> {
|
||||
getMetrics(pvcName: string, namespace: string): Promise<IPvcMetrics> {
|
||||
return metricsApi.getMetrics({
|
||||
diskUsage: { category: 'pvc', pvc: pvcName },
|
||||
diskCapacity: { category: 'pvc', pvc: pvcName }
|
||||
diskUsage: { category: "pvc", pvc: pvcName },
|
||||
diskCapacity: { category: "pvc", pvc: pvcName }
|
||||
}, {
|
||||
namespace
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ export interface JsonApiConfig {
|
||||
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
||||
static reqInitDefault: RequestInit = {
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
"content-type": "application/json"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,9 +132,9 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
||||
protected writeLog(log: JsonApiLog) {
|
||||
if (!this.config.debug) return;
|
||||
const { method, reqUrl, ...params } = log;
|
||||
let textStyle = 'font-weight: bold;';
|
||||
if (params.data) textStyle += 'background: green; color: white;';
|
||||
if (params.error) textStyle += 'background: red; color: white;';
|
||||
let textStyle = "font-weight: bold;";
|
||||
if (params.data) textStyle += "background: green; color: white;";
|
||||
if (params.error) textStyle += "background: red; color: white;";
|
||||
console.log(`%c${method} ${reqUrl}`, textStyle, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export function parseKubeApi(path: string): IKubeApiParsed {
|
||||
* 3. otherwise assume apiVersion <- left[0]
|
||||
* 4. always resource, name <- left[(0 or 1)+1..]
|
||||
*/
|
||||
if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
|
||||
if (left[0].includes(".") || left[1].match(/^v[0-9]/)) {
|
||||
[apiGroup, apiVersion] = left;
|
||||
resource = left.slice(2).join("/");
|
||||
} else {
|
||||
|
||||
@@ -142,7 +142,7 @@ export class KubeWatchApi {
|
||||
|
||||
protected writeLog(...data: any[]) {
|
||||
if (isDevelopment) {
|
||||
console.log('%cKUBE-WATCH-API:', `font-weight: bold`, ...data);
|
||||
console.log("%cKUBE-WATCH-API:", `font-weight: bold`, ...data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@ export class TerminalApi extends WebSocketApi {
|
||||
}
|
||||
|
||||
reconnect() {
|
||||
const { reconnectDelaySeconds } = this.params;
|
||||
super.reconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ export class WebSocketApi {
|
||||
reconnect() {
|
||||
const { reconnectDelaySeconds } = this.params;
|
||||
if (!reconnectDelaySeconds) return;
|
||||
this.writeLog('reconnect after', reconnectDelaySeconds + "ms");
|
||||
this.writeLog("reconnect after", reconnectDelaySeconds + "ms");
|
||||
this.reconnectTimer = setTimeout(() => this.connect(), reconnectDelaySeconds * 1000);
|
||||
this.readyState = WebSocketApiState.RECONNECTING;
|
||||
}
|
||||
@@ -136,17 +136,17 @@ export class WebSocketApi {
|
||||
this.onOpen.emit();
|
||||
if (this.params.flushOnOpen) this.flush();
|
||||
this.readyState = WebSocketApiState.OPEN;
|
||||
this.writeLog('%cOPEN', 'color:green;font-weight:bold;', evt);
|
||||
this.writeLog("%cOPEN", "color:green;font-weight:bold;", evt);
|
||||
}
|
||||
|
||||
protected _onMessage(evt: MessageEvent) {
|
||||
const data = this.parseMessage(evt.data);
|
||||
this.onData.emit(data);
|
||||
this.writeLog('%cMESSAGE', 'color:black;font-weight:bold;', data);
|
||||
this.writeLog("%cMESSAGE", "color:black;font-weight:bold;", data);
|
||||
}
|
||||
|
||||
protected _onError(evt: Event) {
|
||||
this.writeLog('%cERROR', 'color:red;font-weight:bold;', evt);
|
||||
this.writeLog("%cERROR", "color:red;font-weight:bold;", evt);
|
||||
}
|
||||
|
||||
protected _onClose(evt: CloseEvent) {
|
||||
@@ -158,7 +158,7 @@ export class WebSocketApi {
|
||||
this.readyState = WebSocketApiState.CLOSED;
|
||||
this.onClose.emit();
|
||||
}
|
||||
this.writeLog('%cCLOSE', `color:${error ? "red" : "black"};font-weight:bold;`, evt);
|
||||
this.writeLog("%cCLOSE", `color:${error ? "red" : "black"};font-weight:bold;`, evt);
|
||||
}
|
||||
|
||||
protected writeLog(...data: any[]) {
|
||||
|
||||
@@ -66,7 +66,7 @@ export class AddCluster extends React.Component {
|
||||
userStore.kubeConfigPath = filePath; // save to store
|
||||
} catch (err) {
|
||||
Notifications.error(
|
||||
<div>Can't setup <code>{filePath}</code> as kubeconfig: {String(err)}</div>
|
||||
<div>Can't setup <code>{filePath}</code> as kubeconfig: {String(err)}</div>
|
||||
);
|
||||
if (throwError) {
|
||||
throw err;
|
||||
@@ -196,9 +196,9 @@ export class AddCluster extends React.Component {
|
||||
return (
|
||||
<p>
|
||||
Add clusters by clicking the <span className="text-primary">Add Cluster</span> button.
|
||||
You'll need to obtain a working kubeconfig for the cluster you want to add.
|
||||
You'll need to obtain a working kubeconfig for the cluster you want to add.
|
||||
You can either browse it from the file system or paste it as a text from the clipboard.
|
||||
Read more about adding clusters <a href={`${docsUrl}/latest/clusters/adding-clusters/`} target="_blank">here</a>.
|
||||
Read more about adding clusters <a href={`${docsUrl}/latest/clusters/adding-clusters/`} rel="noreferrer" target="_blank">here</a>.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
@@ -300,7 +300,7 @@ export class AddCluster extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
onKubeConfigInputBlur = (evt: React.FocusEvent<HTMLInputElement>) => {
|
||||
onKubeConfigInputBlur = () => {
|
||||
const isChanged = this.kubeConfigPath !== userStore.kubeConfigPath;
|
||||
if (isChanged) {
|
||||
this.kubeConfigPath = this.kubeConfigPath.replace("~", os.homedir());
|
||||
@@ -354,7 +354,7 @@ export class AddCluster extends React.Component {
|
||||
theme="round-black"
|
||||
/>
|
||||
<small className="hint">
|
||||
{'A HTTP proxy server URL (format: http://<address>:<port>).'}
|
||||
{"A HTTP proxy server URL (format: http://<address>:<port>)."}
|
||||
</small>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -93,11 +93,11 @@ export class HelmChartDetails extends Component<Props> {
|
||||
/>
|
||||
</DrawerItem>
|
||||
<DrawerItem name={_i18n._(t`Home`)}>
|
||||
<a href={selectedChart.getHome()} target="_blank">{selectedChart.getHome()}</a>
|
||||
<a href={selectedChart.getHome()} target="_blank" rel="noreferrer">{selectedChart.getHome()}</a>
|
||||
</DrawerItem>
|
||||
<DrawerItem name={_i18n._(t`Maintainers`)} className="maintainers">
|
||||
{selectedChart.getMaintainers().map(({ name, email, url }) =>
|
||||
<a key={name} href={url || `mailto:${email}`} target="_blank">{name}</a>
|
||||
<a key={name} href={url || `mailto:${email}`} target="_blank" rel="noreferrer">{name}</a>
|
||||
)}
|
||||
</DrawerItem>
|
||||
{selectedChart.getKeywords().length > 0 && (
|
||||
|
||||
@@ -84,7 +84,7 @@ export class HelmCharts extends Component<Props> {
|
||||
|
||||
]}
|
||||
renderTableContents={(chart: HelmChart) => [
|
||||
<figure>
|
||||
<figure key="image">
|
||||
<img
|
||||
src={chart.getIcon() || require("./helm-placeholder.svg")}
|
||||
onLoad={evt => evt.currentTarget.classList.add("visible")}
|
||||
|
||||
@@ -56,8 +56,9 @@ export class HelmReleaseMenu extends React.Component<Props> {
|
||||
{...menuProps}
|
||||
className={cssNames("HelmReleaseMenu", className)}
|
||||
removeAction={this.remove}
|
||||
children={this.renderContent()}
|
||||
/>
|
||||
>
|
||||
{this.renderContent()}
|
||||
</MenuActions>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ export class HelmReleases extends Component<Props> {
|
||||
<div>
|
||||
<Trans>Remove <b>{releaseNames}</b>?</Trans>
|
||||
<p className="warning">
|
||||
<Trans>Note: StatefulSet Volumes won't be deleted automatically</Trans>
|
||||
<Trans>Note: StatefulSet Volumes won't be deleted automatically</Trans>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
@@ -146,4 +146,4 @@ export class HelmReleases extends Component<Props> {
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@ export class ClusterAccessibleNamespaces extends React.Component<Props> {
|
||||
return (
|
||||
<>
|
||||
<SubTitle title="Accessible Namespaces" />
|
||||
<p><Trans>This setting is useful for manually specifying which namespaces you have access to. This is useful when you don't have permissions to list namespaces.</Trans></p>
|
||||
<p><Trans>This setting is useful for manually specifying which namespaces you have access to. This is useful when you don't have permissions to list namespaces.</Trans></p>
|
||||
<EditableList
|
||||
placeholder={_i18n._("Add new namespace...")}
|
||||
add={(newNamespace) => {
|
||||
|
||||
@@ -28,7 +28,7 @@ export class ClusterIconSetting extends React.Component<Props> {
|
||||
try {
|
||||
if (file) {
|
||||
const buf = Buffer.from(await file.arrayBuffer());
|
||||
cluster.preferences.icon = `data:${file.type};base64,${buf.toString('base64')}`;
|
||||
cluster.preferences.icon = `data:${file.type};base64,${buf.toString("base64")}`;
|
||||
} else {
|
||||
// this has to be done as a seperate branch (and not always) because `cluster`
|
||||
// is observable and triggers an update loop.
|
||||
|
||||
@@ -78,7 +78,7 @@ export class ClusterPrometheusSetting extends React.Component<Props> {
|
||||
<SubTitle title="Prometheus"/>
|
||||
<p>
|
||||
Use pre-installed Prometheus service for metrics. Please refer to the{" "}
|
||||
<a href="https://github.com/lensapp/lens/blob/master/troubleshooting/custom-prometheus.md" target="_blank">guide</a>{" "}
|
||||
<a href="https://github.com/lensapp/lens/blob/master/troubleshooting/custom-prometheus.md" target="_blank" rel="noreferrer">guide</a>{" "}
|
||||
for possible configuration changes.
|
||||
</p>
|
||||
<p>Prometheus installation method.</p>
|
||||
@@ -103,11 +103,11 @@ export class ClusterPrometheusSetting extends React.Component<Props> {
|
||||
/>
|
||||
<small className="hint">
|
||||
An address to an existing Prometheus installation{" "}
|
||||
({'<namespace>/<service>:<port>'}). Lens tries to auto-detect address if left empty.
|
||||
({"<namespace>/<service>:<port>"}). Lens tries to auto-detect address if left empty.
|
||||
</small>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,18 @@ export class Features extends React.Component<Props> {
|
||||
return (
|
||||
<div>
|
||||
<h2>Features</h2>
|
||||
{ clusterFeatureRegistry.getItems().map((f) => {
|
||||
return (
|
||||
<InstallFeature cluster={cluster} feature={f.feature}>
|
||||
<>
|
||||
<SubTitle title={f.title}/>
|
||||
<p><f.components.Description /></p>
|
||||
</>
|
||||
</InstallFeature>
|
||||
);
|
||||
})}
|
||||
{
|
||||
clusterFeatureRegistry
|
||||
.getItems()
|
||||
.map((f) => (
|
||||
<InstallFeature key={f.title} cluster={cluster} feature={f.feature}>
|
||||
<>
|
||||
<SubTitle title={f.title} />
|
||||
<p><f.components.Description /></p>
|
||||
</>
|
||||
</InstallFeature>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export class HorizontalPodAutoscalers extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(hpa: HorizontalPodAutoscaler) => [
|
||||
hpa.getName(),
|
||||
<KubeObjectStatusIcon object={hpa} />,
|
||||
<KubeObjectStatusIcon key="icon" object={hpa} />,
|
||||
hpa.getNs(),
|
||||
this.getTargets(hpa),
|
||||
hpa.getMinPods(),
|
||||
@@ -85,4 +85,3 @@ export class HorizontalPodAutoscalers extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,9 @@ import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { RouteComponentProps } from "react-router";
|
||||
import { configMapsStore } from "./config-maps.store";
|
||||
import { ConfigMap, configMapApi } from "../../api/endpoints/configmap.api";
|
||||
import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
||||
import { ConfigMap } from "../../api/endpoints/configmap.api";
|
||||
import { KubeObjectListLayout } from "../kube-object";
|
||||
import { IConfigMapsRouteParams } from "./config-maps.route";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
|
||||
enum sortBy {
|
||||
@@ -48,7 +46,7 @@ export class ConfigMaps extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(configMap: ConfigMap) => [
|
||||
configMap.getName(),
|
||||
<KubeObjectStatusIcon object={configMap}/>,
|
||||
<KubeObjectStatusIcon key="icon" object={configMap}/>,
|
||||
configMap.getNs(),
|
||||
configMap.getKeys().join(", "),
|
||||
configMap.getAge(),
|
||||
@@ -57,4 +55,3 @@ export class ConfigMaps extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -19,18 +19,17 @@ export class PodDisruptionBudgetDetails extends React.Component<Props> {
|
||||
render() {
|
||||
const { object: pdb } = this.props;
|
||||
if (!pdb) return null;
|
||||
const { status, spec } = pdb;
|
||||
const selectors = pdb.getSelectors();
|
||||
return (
|
||||
<div className="PdbDetails">
|
||||
<KubeObjectMeta object={pdb}/>
|
||||
|
||||
{selectors.length > 0 &&
|
||||
<DrawerItem name={<Trans>Selector</Trans>} labelsOnly>
|
||||
{
|
||||
selectors.map(label => <Badge key={label} label={label}/>)
|
||||
}
|
||||
</DrawerItem>
|
||||
<DrawerItem name={<Trans>Selector</Trans>} labelsOnly>
|
||||
{
|
||||
selectors.map(label => <Badge key={label} label={label}/>)
|
||||
}
|
||||
</DrawerItem>
|
||||
}
|
||||
|
||||
<DrawerItem name={<Trans>Min Available</Trans>}>
|
||||
|
||||
@@ -3,13 +3,9 @@ import "./pod-disruption-budgets.scss";
|
||||
import * as React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { RouteComponentProps } from "react-router";
|
||||
import { podDisruptionBudgetsStore } from "./pod-disruption-budgets.store";
|
||||
import { PodDisruptionBudget, pdbApi } from "../../api/endpoints/poddisruptionbudget.api";
|
||||
import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
||||
import { PodDisruptionBudget } from "../../api/endpoints/poddisruptionbudget.api";
|
||||
import { KubeObjectDetailsProps, KubeObjectListLayout } from "../kube-object";
|
||||
import { IPodDisruptionBudgetsRouteParams } from "./pod-disruption-budgets.route";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
|
||||
enum sortBy {
|
||||
@@ -58,7 +54,7 @@ export class PodDisruptionBudgets extends React.Component<Props> {
|
||||
renderTableContents={(pdb: PodDisruptionBudget) => {
|
||||
return [
|
||||
pdb.getName(),
|
||||
<KubeObjectStatusIcon object={pdb} />,
|
||||
<KubeObjectStatusIcon key="icon" object={pdb} />,
|
||||
pdb.getNs(),
|
||||
pdb.getMinAvailable(),
|
||||
pdb.getMaxUnavailable(),
|
||||
|
||||
@@ -63,7 +63,7 @@ export class AddQuotaDialog extends React.Component<Props> {
|
||||
|
||||
@computed get quotaEntries() {
|
||||
return Object.entries(this.quotas)
|
||||
.filter(([type, value]) => !!value.trim());
|
||||
.filter(([, value]) => !!value.trim());
|
||||
}
|
||||
|
||||
@computed get quotaOptions() {
|
||||
@@ -201,4 +201,4 @@ export class AddQuotaDialog extends React.Component<Props> {
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,6 @@ import { ReplicaSetDetails } from "../+workloads-replicasets";
|
||||
interface Props extends KubeObjectDetailsProps<ResourceQuota> {
|
||||
}
|
||||
|
||||
const onlyNumbers = /$[0-9]*^/g;
|
||||
|
||||
function transformUnit(name: string, value: string): number {
|
||||
if (name.includes("memory") || name.includes("storage")) {
|
||||
return unitsToBytes(value);
|
||||
|
||||
@@ -4,13 +4,11 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { RouteComponentProps } from "react-router";
|
||||
import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
||||
import { KubeObjectListLayout } from "../kube-object";
|
||||
import { ResourceQuota, resourceQuotaApi } from "../../api/endpoints/resource-quota.api";
|
||||
import { ResourceQuota } from "../../api/endpoints/resource-quota.api";
|
||||
import { AddQuotaDialog } from "./add-quota-dialog";
|
||||
import { resourceQuotaStore } from "./resource-quotas.store";
|
||||
import { IResourceQuotaRouteParams } from "./resource-quotas.route";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
|
||||
enum sortBy {
|
||||
@@ -47,7 +45,7 @@ export class ResourceQuotas extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(resourceQuota: ResourceQuota) => [
|
||||
resourceQuota.getName(),
|
||||
<KubeObjectStatusIcon object={resourceQuota}/>,
|
||||
<KubeObjectStatusIcon key="icon" object={resourceQuota}/>,
|
||||
resourceQuota.getNs(),
|
||||
resourceQuota.getAge(),
|
||||
]}
|
||||
|
||||
@@ -4,14 +4,12 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { RouteComponentProps } from "react-router";
|
||||
import { Secret, secretsApi } from "../../api/endpoints";
|
||||
import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
||||
import { Secret } from "../../api/endpoints";
|
||||
import { AddSecretDialog } from "./add-secret-dialog";
|
||||
import { ISecretsRouteParams } from "./secrets.route";
|
||||
import { KubeObjectListLayout } from "../kube-object";
|
||||
import { Badge } from "../badge";
|
||||
import { secretsStore } from "./secrets.store";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
|
||||
enum sortBy {
|
||||
@@ -57,7 +55,7 @@ export class Secrets extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(secret: Secret) => [
|
||||
secret.getName(),
|
||||
<KubeObjectStatusIcon object={secret} />,
|
||||
<KubeObjectStatusIcon key="icon" object={secret} />,
|
||||
secret.getNs(),
|
||||
secret.getLabels().map(label => <Badge key={label} label={label}/>),
|
||||
secret.getKeys().join(", "),
|
||||
|
||||
@@ -4,8 +4,7 @@ import React from "react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { Link } from "react-router-dom";
|
||||
import { observer } from "mobx-react";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { crdApi, CustomResourceDefinition } from "../../api/endpoints/crd.api";
|
||||
import { CustomResourceDefinition } from "../../api/endpoints/crd.api";
|
||||
import { cssNames } from "../../utils";
|
||||
import { AceEditor } from "../ace-editor";
|
||||
import { Badge } from "../badge";
|
||||
|
||||
@@ -90,19 +90,16 @@ export class CrdList extends React.Component {
|
||||
{ title: <Trans>Scope</Trans>, className: "scope", sortBy: sortBy.scope },
|
||||
{ title: <Trans>Age</Trans>, className: "age", sortBy: sortBy.age },
|
||||
]}
|
||||
renderTableContents={(crd: CustomResourceDefinition) => {
|
||||
return [
|
||||
<Link to={crd.getResourceUrl()} onClick={stopPropagation}>
|
||||
{crd.getResourceTitle()}
|
||||
</Link>,
|
||||
crd.getGroup(),
|
||||
crd.getVersion(),
|
||||
crd.getScope(),
|
||||
crd.getAge(),
|
||||
];
|
||||
}}
|
||||
renderTableContents={(crd: CustomResourceDefinition) => [
|
||||
<Link key="link" to={crd.getResourceUrl()} onClick={stopPropagation}>
|
||||
{crd.getResourceTitle()}
|
||||
</Link>,
|
||||
crd.getGroup(),
|
||||
crd.getVersion(),
|
||||
crd.getScope(),
|
||||
crd.getAge(),
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ export class Events extends React.Component<Props> {
|
||||
},
|
||||
event.getNs(),
|
||||
kind,
|
||||
<Link to={detailsUrl} title={name} onClick={stopPropagation}>{name}</Link>,
|
||||
<Link key="link" to={detailsUrl} title={name} onClick={stopPropagation}>{name}</Link>,
|
||||
event.getSource(),
|
||||
event.count,
|
||||
event.getAge(),
|
||||
|
||||
@@ -157,7 +157,7 @@ export class Extensions extends React.Component {
|
||||
};
|
||||
|
||||
installOnDrop = (files: File[]) => {
|
||||
logger.info('Install from D&D');
|
||||
logger.info("Install from D&D");
|
||||
return this.requestInstall(
|
||||
files.map(file => ({
|
||||
fileName: path.basename(file.path),
|
||||
@@ -405,7 +405,7 @@ export class Extensions extends React.Component {
|
||||
The features that Lens includes out-of-the-box are just the start.
|
||||
Lens extensions let you add new features to your installation to support your workflow.
|
||||
Rich extensibility model lets extension authors plug directly into the Lens UI and contribute functionality through the same APIs used by Lens itself.
|
||||
Check out documentation to <a href={`${docsUrl}/latest/extensions/usage/`} target="_blank">learn more</a>.
|
||||
Check out documentation to <a href={`${docsUrl}/latest/extensions/usage/`} target="_blank" rel="noreferrer">learn more</a>.
|
||||
</div>
|
||||
|
||||
<div className="install-extension flex column gaps">
|
||||
@@ -438,7 +438,7 @@ export class Extensions extends React.Component {
|
||||
onClick={this.installFromUrlOrPath}
|
||||
/>
|
||||
<small className="hint">
|
||||
<Trans><b>Pro-Tip</b>: you can drag & drop extension's tarball-file to install</Trans>
|
||||
<Trans><b>Pro-Tip</b>: you can drag & drop extension's tarball-file to install</Trans>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ export class Namespaces extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(item: Namespace) => [
|
||||
item.getName(),
|
||||
<KubeObjectStatusIcon object={item} />,
|
||||
<KubeObjectStatusIcon key="icon" object={item} />,
|
||||
item.getLabels().map(label => <Badge key={label} label={label}/>),
|
||||
item.getAge(),
|
||||
{ title: item.getStatus(), className: item.getStatus().toLowerCase() },
|
||||
|
||||
@@ -7,7 +7,6 @@ import { DrawerTitle } from "../drawer";
|
||||
import { KubeEventDetails } from "../+events/kube-event-details";
|
||||
import { KubeObjectDetailsProps } from "../kube-object";
|
||||
import { Endpoint } from "../../api/endpoints";
|
||||
import { _i18n } from "../../i18n";
|
||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||
import { EndpointSubsetList } from "./endpoint-subset-list";
|
||||
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
||||
@@ -25,11 +24,9 @@ export class EndpointDetails extends React.Component<Props> {
|
||||
<KubeObjectMeta object={endpoint}/>
|
||||
<DrawerTitle title={<Trans>Subsets</Trans>}/>
|
||||
{
|
||||
endpoint.getEndpointSubsets().map((subset) => {
|
||||
return(
|
||||
<EndpointSubsetList subset={subset} endpoint={endpoint}/>
|
||||
);
|
||||
})
|
||||
endpoint.getEndpointSubsets().map((subset) => (
|
||||
<EndpointSubsetList key={subset.toString()} subset={subset} endpoint={endpoint} />
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,8 +3,6 @@ import "./endpoint-subset-list.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EndpointSubset, Endpoint, EndpointAddress} from "../../api/endpoints";
|
||||
import { _i18n } from "../../i18n";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { autobind } from "../../utils";
|
||||
|
||||
@@ -43,7 +43,7 @@ export class Endpoints extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(endpoint: Endpoint) => [
|
||||
endpoint.getName(),
|
||||
<KubeObjectStatusIcon object={endpoint} />,
|
||||
<KubeObjectStatusIcon key="icon" object={endpoint} />,
|
||||
endpoint.getNs(),
|
||||
endpoint.toString(),
|
||||
endpoint.getAge(),
|
||||
|
||||
@@ -100,12 +100,12 @@ export class IngressDetails extends React.Component<Props> {
|
||||
const ingressPoints = status?.loadBalancer?.ingress;
|
||||
const { metrics } = ingressStore;
|
||||
const metricTabs = [
|
||||
<Trans>Network</Trans>,
|
||||
<Trans>Duration</Trans>,
|
||||
<Trans key="network">Network</Trans>,
|
||||
<Trans key="network">Duration</Trans>,
|
||||
];
|
||||
|
||||
const { serviceName, servicePort } = ingress.getServiceNamePort();
|
||||
|
||||
|
||||
return (
|
||||
<div className="IngressDetails">
|
||||
<ResourceMetrics
|
||||
|
||||
@@ -45,7 +45,7 @@ export class Ingresses extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(ingress: Ingress) => [
|
||||
ingress.getName(),
|
||||
<KubeObjectStatusIcon object={ingress} />,
|
||||
<KubeObjectStatusIcon key="icon" object={ingress} />,
|
||||
ingress.getNs(),
|
||||
ingress.getLoadBalancers().map(lb => <p key={lb}>{lb}</p>),
|
||||
ingress.getRoutes().map(route => <p key={route}>{route}</p>),
|
||||
|
||||
@@ -43,7 +43,7 @@ export class NetworkPolicies extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(item: NetworkPolicy) => [
|
||||
item.getName(),
|
||||
<KubeObjectStatusIcon object={item} />,
|
||||
<KubeObjectStatusIcon key="icon" object={item} />,
|
||||
item.getNs(),
|
||||
item.getTypes().join(", "),
|
||||
item.getAge(),
|
||||
|
||||
@@ -61,7 +61,7 @@ export class Services extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(service: Service) => [
|
||||
service.getName(),
|
||||
<KubeObjectStatusIcon object={service} />,
|
||||
<KubeObjectStatusIcon key="icon" object={service} />,
|
||||
service.getNs(),
|
||||
service.getType(),
|
||||
service.getClusterIp(),
|
||||
|
||||
@@ -26,11 +26,9 @@ export const NodeCharts = observer(() => {
|
||||
const [
|
||||
memoryUsage,
|
||||
memoryRequests,
|
||||
memoryLimits,
|
||||
memoryCapacity,
|
||||
cpuUsage,
|
||||
cpuRequests,
|
||||
cpuLimits,
|
||||
cpuCapacity,
|
||||
podUsage,
|
||||
podCapacity,
|
||||
@@ -151,4 +149,4 @@ export const NodeCharts = observer(() => {
|
||||
data={{ datasets: datasets[tabId] }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -49,10 +49,10 @@ export class NodeDetails extends React.Component<Props> {
|
||||
const childPods = podsStore.getPodsByNode(node.getName());
|
||||
const metrics = nodesStore.nodeMetrics;
|
||||
const metricTabs = [
|
||||
<Trans>CPU</Trans>,
|
||||
<Trans>Memory</Trans>,
|
||||
<Trans>Disk</Trans>,
|
||||
<Trans>Pods</Trans>,
|
||||
<Trans key="cpu">CPU</Trans>,
|
||||
<Trans key="memory">Memory</Trans>,
|
||||
<Trans key="disk">Disk</Trans>,
|
||||
<Trans key="pods">Pods</Trans>,
|
||||
];
|
||||
return (
|
||||
<div className="NodeDetails">
|
||||
|
||||
@@ -163,7 +163,7 @@ export class Nodes extends React.Component<Props> {
|
||||
const tooltipId = `node-taints-${node.getId()}`;
|
||||
return [
|
||||
node.getName(),
|
||||
<KubeObjectStatusIcon object={node} />,
|
||||
<KubeObjectStatusIcon key="icon" object={node} />,
|
||||
this.renderCpuUsage(node),
|
||||
this.renderMemoryUsage(node),
|
||||
this.renderDiskUsage(node),
|
||||
|
||||
@@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { KubeObjectListLayout } from "../kube-object";
|
||||
import { podSecurityPoliciesStore } from "./pod-security-policies.store";
|
||||
import { PodSecurityPolicy, pspApi } from "../../api/endpoints";
|
||||
import { PodSecurityPolicy } from "../../api/endpoints";
|
||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
|
||||
enum sortBy {
|
||||
@@ -45,7 +45,7 @@ export class PodSecurityPolicies extends React.Component {
|
||||
renderTableContents={(item: PodSecurityPolicy) => {
|
||||
return [
|
||||
item.getName(),
|
||||
<KubeObjectStatusIcon object={item} />,
|
||||
<KubeObjectStatusIcon key="icon" object={item} />,
|
||||
item.isPrivileged() ? <Trans>Yes</Trans> : <Trans>No</Trans>,
|
||||
item.getVolumes().join(", "),
|
||||
item.getAge(),
|
||||
|
||||
@@ -48,9 +48,9 @@ export class PodSecurityPolicyDetails extends React.Component<Props> {
|
||||
}
|
||||
const {
|
||||
allowedHostPaths, allowedCapabilities, allowedCSIDrivers, allowedFlexVolumes, allowedProcMountTypes,
|
||||
allowedUnsafeSysctls, allowPrivilegeEscalation, defaultAddCapabilities, defaultAllowPrivilegeEscalation,
|
||||
forbiddenSysctls, fsGroup, hostIPC, hostNetwork, hostPID, hostPorts, privileged, readOnlyRootFilesystem,
|
||||
requiredDropCapabilities, runAsGroup, runAsUser, runtimeClass, seLinux, supplementalGroups, volumes
|
||||
allowedUnsafeSysctls, allowPrivilegeEscalation, defaultAddCapabilities, forbiddenSysctls, fsGroup,
|
||||
hostIPC, hostNetwork, hostPID, hostPorts, privileged, readOnlyRootFilesystem, requiredDropCapabilities,
|
||||
runAsGroup, runAsUser, runtimeClass, seLinux, supplementalGroups, volumes,
|
||||
} = psp.spec;
|
||||
return (
|
||||
<div className="PodSecurityPolicyDetails">
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Checkbox } from '../checkbox';
|
||||
import { Input, InputValidators } from '../input';
|
||||
import { SubTitle } from '../layout/sub-title';
|
||||
import { UserPreferences, userStore } from '../../../common/user-store';
|
||||
import { observer } from 'mobx-react';
|
||||
import { bundledKubectlPath } from '../../../main/kubectl';
|
||||
import { SelectOption, Select } from '../select';
|
||||
import React, { useState } from "react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { Checkbox } from "../checkbox";
|
||||
import { Input, InputValidators } from "../input";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { UserPreferences, userStore } from "../../../common/user-store";
|
||||
import { observer } from "mobx-react";
|
||||
import { bundledKubectlPath } from "../../../main/kubectl";
|
||||
import { SelectOption, Select } from "../select";
|
||||
|
||||
export const KubectlBinaries = observer(({ preferences }: { preferences: UserPreferences }) => {
|
||||
const [downloadPath, setDownloadPath] = useState(preferences.downloadBinariesPath || "");
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { StorageClass, storageClassApi } from "../../api/endpoints/storage-class.api";
|
||||
import { StorageClass } from "../../api/endpoints/storage-class.api";
|
||||
import { KubeObjectListLayout } from "../kube-object";
|
||||
import { IStorageClassesRouteParams } from "./storage-classes.route";
|
||||
import { storageClassStore } from "./storage-class.store";
|
||||
@@ -48,7 +48,7 @@ export class StorageClasses extends React.Component<Props> {
|
||||
]}
|
||||
renderTableContents={(storageClass: StorageClass) => [
|
||||
storageClass.getName(),
|
||||
<KubeObjectStatusIcon object={storageClass} />,
|
||||
<KubeObjectStatusIcon key="icon" object={storageClass} />,
|
||||
storageClass.provisioner,
|
||||
storageClass.getReclaimPolicy(),
|
||||
storageClass.isDefault() ? <Trans>Yes</Trans> : null,
|
||||
|
||||
@@ -42,7 +42,7 @@ export class PersistentVolumeClaimDetails extends React.Component<Props> {
|
||||
const { metrics } = volumeClaimStore;
|
||||
const pods = volumeClaim.getPods(podsStore.items);
|
||||
const metricTabs = [
|
||||
<Trans>Disk</Trans>
|
||||
<Trans key="disk">Disk</Trans>
|
||||
];
|
||||
return (
|
||||
<div className="PersistentVolumeClaimDetails">
|
||||
|
||||
Loaded 100 of 199 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user