1
0
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:
Sebastian Malton 2020-11-27 08:48:38 -05:00 committed by GitHub
parent 10eb082854
commit 7451869c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
199 changed files with 1178 additions and 807 deletions

View File

@ -1,62 +1,92 @@
const packageJson = require("./package.json");
module.exports = {
ignorePatterns: [
"**/node_modules/**/*",
"**/dist/**/*",
],
settings: {
react: {
version: packageJson.devDependencies.react || "detect",
}
},
overrides: [
{
files: [
"src/renderer/**/*.js",
"build/**/*.js",
"extensions/**/*.js"
"**/*.js"
],
extends: [
'eslint:recommended',
"eslint:recommended",
],
env: {
node: true
},
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
sourceType: "module",
},
plugins: [
"unused-imports"
],
rules: {
"indent": ["error", 2, {
"SwitchCase": 1,
}],
"no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
}
],
"quotes": ["error", "double", {
"avoidEscape": true,
"allowTemplateLiterals": true,
}],
"semi": ["error", "always"],
"object-shorthand": "error",
}
},
{
files: [
"build/*.ts",
"src/**/*.ts",
"integration/**/*.ts",
"src/extensions/**/*.ts*",
"extensions/**/*.ts*",
"__mocks__/*.ts",
"**/*.ts",
],
parser: "@typescript-eslint/parser",
extends: [
'plugin:@typescript-eslint/recommended',
"plugin:@typescript-eslint/recommended",
],
plugins: [
"unused-imports"
],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
sourceType: "module",
},
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports-ts": "error",
"unused-imports/no-unused-vars-ts": [
"warn", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
}
],
"indent": ["error", 2, {
"SwitchCase": 1,
}],
"quotes": ["error", "double", {
"avoidEscape": true,
"allowTemplateLiterals": true,
}],
"semi": "off",
"@typescript-eslint/semi": ["error"],
"object-shorthand": "error",
@ -64,21 +94,24 @@ module.exports = {
},
{
files: [
"src/renderer/**/*.tsx",
"**/*.tsx",
],
parser: "@typescript-eslint/parser",
plugins: [
"unused-imports"
],
extends: [
'plugin:@typescript-eslint/recommended',
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
sourceType: "module",
jsx: true,
},
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-empty-interface": "off",
@ -87,9 +120,23 @@ module.exports = {
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-empty-function": "off",
"react/display-name": "off",
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports-ts": "error",
"unused-imports/no-unused-vars-ts": [
"warn", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
}
],
"indent": ["error", 2, {
"SwitchCase": 1,
}],
"quotes": ["error", "double", {
"avoidEscape": true,
"allowTemplateLiterals": true,
}],
"semi": "off",
"@typescript-eslint/semi": ["error"],
"object-shorthand": "error",

View File

@ -4,9 +4,7 @@ module.exports = {
app: {
getVersion: jest.fn().mockReturnValue("3.0.0"),
getLocale: jest.fn().mockRejectedValue("en"),
getPath: jest.fn((name: string) => {
return "tmp";
}),
getPath: jest.fn(() => "tmp"),
},
remote: {
app: {

View File

@ -92,12 +92,12 @@ class KubectlDownloader {
}
const downloadVersion = packageInfo.config.bundledKubectlVersion;
const baseDir = path.join(process.env.INIT_CWD, 'binaries', 'client');
const baseDir = path.join(process.env.INIT_CWD, "binaries", "client");
const downloads = [
{ platform: 'linux', arch: 'amd64', target: path.join(baseDir, 'linux', 'x64', 'kubectl') },
{ platform: 'darwin', arch: 'amd64', target: path.join(baseDir, 'darwin', 'x64', 'kubectl') },
{ platform: 'windows', arch: 'amd64', target: path.join(baseDir, 'windows', 'x64', 'kubectl.exe') },
{ platform: 'windows', arch: '386', target: path.join(baseDir, 'windows', 'ia32', 'kubectl.exe') }
{ platform: "linux", arch: "amd64", target: path.join(baseDir, "linux", "x64", "kubectl") },
{ platform: "darwin", arch: "amd64", target: path.join(baseDir, "darwin", "x64", "kubectl") },
{ platform: "windows", arch: "amd64", target: path.join(baseDir, "windows", "x64", "kubectl.exe") },
{ platform: "windows", arch: "386", target: path.join(baseDir, "windows", "ia32", "kubectl.exe") }
];
downloads.forEach((dlOpts) => {

View File

@ -1,8 +1,8 @@
const { notarize } = require('electron-notarize');
const { notarize } = require("electron-notarize");
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
if (electronPlatformName !== "darwin") {
return;
}
if (!process.env.APPLEID || !process.env.APPLEIDPASS) {
@ -12,7 +12,7 @@ exports.default = async function notarizing(context) {
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: 'io.kontena.lens-app',
appBundleId: "io.kontena.lens-app",
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLEID,
appleIdPassword: process.env.APPLEIDPASS,

View File

@ -2,10 +2,10 @@ import { LensMainExtension } from "@k8slens/extensions";
export default class ExampleExtensionMain extends LensMainExtension {
onActivate() {
console.log('EXAMPLE EXTENSION MAIN: ACTIVATED', this.name, this.id);
console.log("EXAMPLE EXTENSION MAIN: ACTIVATED", this.name, this.id);
}
onDeactivate() {
console.log('EXAMPLE EXTENSION MAIN: DEACTIVATED', this.name, this.id);
console.log("EXAMPLE EXTENSION MAIN: DEACTIVATED", this.name, this.id);
}
}

View File

@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = [
{
entry: './main.ts',
entry: "./main.ts",
context: __dirname,
target: "electron-main",
mode: "production",
@ -10,7 +10,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -23,16 +23,16 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
},
{
entry: './renderer.tsx',
entry: "./renderer.tsx",
context: __dirname,
target: "electron-renderer",
mode: "production",
@ -40,7 +40,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -53,13 +53,13 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'renderer.js',
path: path.resolve(__dirname, 'dist'),
filename: "renderer.js",
path: path.resolve(__dirname, "dist"),
},
},
];

View File

@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = [
{
entry: './renderer.tsx',
entry: "./renderer.tsx",
context: __dirname,
target: "electron-renderer",
mode: "production",
@ -10,7 +10,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -23,13 +23,13 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'renderer.js',
path: path.resolve(__dirname, 'dist'),
filename: "renderer.js",
path: path.resolve(__dirname, "dist"),
},
},
];

View File

@ -1,10 +1,10 @@
import path from "path";
const outputPath = path.resolve(__dirname, 'dist');
const outputPath = path.resolve(__dirname, "dist");
export default [
{
entry: './main.ts',
entry: "./main.ts",
context: __dirname,
target: "electron-main",
mode: "production",
@ -12,7 +12,7 @@ export default [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -22,12 +22,12 @@ export default [
"mobx": "var global.Mobx",
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
extensions: [".tsx", ".ts", ".js"],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'main.js',
filename: "main.js",
path: outputPath,
},
},

View File

@ -7,15 +7,13 @@ export default class ClusterMetricsFeatureExtension extends LensRendererExtensio
{
title: "Metrics Stack",
components: {
Description: () => {
return (
Description: () => (
<span>
Enable timeseries data visualization (Prometheus stack) for your cluster.
Install this only if you don't have existing Prometheus stack installed.
You can see preview of manifests <a href="https://github.com/lensapp/lens/tree/master/extensions/lens-metrics/resources" target="_blank">here</a>.
Install this only if you don&apos;t have existing Prometheus stack installed.
You can see preview of manifests <a href="https://github.com/lensapp/lens/tree/master/extensions/lens-metrics/resources" rel="noreferrer" target="_blank">here</a>.
</span>
);
}
)
},
feature: new MetricsFeature()
}

View File

@ -54,8 +54,8 @@ export class MetricsFeature extends ClusterFeature.Feature {
const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass);
const scs = await storageClassApi.list();
this.templateContext.persistence.enabled = scs.some(sc => (
sc.metadata?.annotations?.['storageclass.kubernetes.io/is-default-class'] === 'true' ||
sc.metadata?.annotations?.['storageclass.beta.kubernetes.io/is-default-class'] === 'true'
sc.metadata?.annotations?.["storageclass.kubernetes.io/is-default-class"] === "true" ||
sc.metadata?.annotations?.["storageclass.beta.kubernetes.io/is-default-class"] === "true"
));
super.applyResources(cluster, path.join(__dirname, "../resources/"));

View File

@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = [
{
entry: './renderer.tsx',
entry: "./renderer.tsx",
context: __dirname,
target: "electron-renderer",
mode: "production",
@ -10,7 +10,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -23,13 +23,13 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'renderer.js',
path: path.resolve(__dirname, 'dist'),
filename: "renderer.js",
path: path.resolve(__dirname, "dist"),
},
node: {
__dirname: false

View File

@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = [
{
entry: './renderer.tsx',
entry: "./renderer.tsx",
context: __dirname,
target: "electron-renderer",
mode: "production",
@ -10,7 +10,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -23,13 +23,13 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'renderer.js',
path: path.resolve(__dirname, 'dist'),
filename: "renderer.js",
path: path.resolve(__dirname, "dist"),
},
},
];

View File

@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = [
{
entry: './renderer.tsx',
entry: "./renderer.tsx",
context: __dirname,
target: "electron-renderer",
mode: "production",
@ -10,7 +10,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -23,13 +23,13 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'renderer.js',
path: path.resolve(__dirname, 'dist'),
filename: "renderer.js",
path: path.resolve(__dirname, "dist"),
},
},
];

View File

@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = [
{
entry: './main.ts',
entry: "./main.ts",
context: __dirname,
target: "electron-main",
mode: "production",
@ -10,7 +10,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -23,17 +23,17 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
},
{
entry: './renderer.tsx',
entry: "./renderer.tsx",
context: __dirname,
target: "electron-renderer",
mode: "production",
@ -41,7 +41,7 @@ module.exports = [
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
use: "ts-loader",
exclude: /node_modules/,
},
],
@ -55,13 +55,13 @@ module.exports = [
}
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
extensions: [ ".tsx", ".ts", ".js" ],
},
output: {
libraryTarget: "commonjs2",
globalObject: "this",
filename: 'renderer.js',
path: path.resolve(__dirname, 'dist'),
filename: "renderer.js",
path: path.resolve(__dirname, "dist"),
},
},
];

View File

@ -8,9 +8,6 @@ import { Application } from "spectron";
import * as util from "../helpers/utils";
import { spawnSync } from "child_process";
const describeif = (condition: boolean) => condition ? describe : describe.skip;
const itif = (condition: boolean) => condition ? it : it.skip;
jest.setTimeout(60000);
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
@ -82,18 +79,18 @@ describe("Lens integration tests", () => {
});
it('shows "add cluster"', async () => {
await app.electron.ipcRenderer.send('test-menu-item-click', "File", "Add Cluster");
await app.electron.ipcRenderer.send("test-menu-item-click", "File", "Add Cluster");
await app.client.waitUntilTextExists("h2", "Add Cluster");
});
describe("preferences page", () => {
it('shows "preferences"', async () => {
const appName: string = process.platform === "darwin" ? "Lens" : "File";
await app.electron.ipcRenderer.send('test-menu-item-click', appName, "Preferences");
await app.electron.ipcRenderer.send("test-menu-item-click", appName, "Preferences");
await app.client.waitUntilTextExists("h2", "Preferences");
});
it('ensures helm repos', async () => {
it("ensures helm repos", async () => {
await app.client.waitUntilTextExists("div.repos #message-bitnami", "bitnami"); // wait for the helm-cli to fetch the bitnami repo
await app.client.click("#HelmRepoSelect"); // click the repo select to activate the drop-down
await app.client.waitUntilTextExists("div.Select__option", ""); // wait for at least one option to appear (any text)
@ -101,12 +98,12 @@ describe("Lens integration tests", () => {
});
it.skip('quits Lens"', async () => {
await app.client.keys(['Meta', 'Q']);
await app.client.keys('Meta');
await app.client.keys(["Meta", "Q"]);
await app.client.keys("Meta");
});
});
describeif(ready)("workspaces", () => {
util.describeIf(ready)("workspaces", () => {
beforeAll(appStart, 20000);
afterAll(async () => {
@ -115,27 +112,27 @@ describe("Lens integration tests", () => {
}
});
it('creates new workspace', async () => {
it("creates new workspace", async () => {
await clickWhatsNew(app);
await app.client.click('#current-workspace .Icon');
await app.client.click("#current-workspace .Icon");
await app.client.click('a[href="/workspaces"]');
await app.client.click('.Workspaces button.Button');
await app.client.click(".Workspaces button.Button");
await app.client.keys("test-workspace");
await app.client.click('.Workspaces .Input.description input');
await app.client.click(".Workspaces .Input.description input");
await app.client.keys("test description");
await app.client.click('.Workspaces .workspace.editing .Icon');
await app.client.click(".Workspaces .workspace.editing .Icon");
await app.client.waitUntilTextExists(".workspace .name a", "test-workspace");
});
it('adds cluster in default workspace', async () => {
it("adds cluster in default workspace", async () => {
await addMinikubeCluster(app);
await app.client.waitUntilTextExists("pre.kube-auth-out", "Authentication proxy started");
await app.client.waitForExist(`iframe[name="minikube"]`);
await app.client.waitForVisible(".ClustersMenu .ClusterIcon.active");
});
it('adds cluster in test-workspace', async () => {
await app.client.click('#current-workspace .Icon');
it("adds cluster in test-workspace", async () => {
await app.client.click("#current-workspace .Icon");
await app.client.waitForVisible('.WorkspaceMenu li[title="test description"]');
await app.client.click('.WorkspaceMenu li[title="test description"]');
await addMinikubeCluster(app);
@ -143,10 +140,10 @@ describe("Lens integration tests", () => {
await app.client.waitForExist(`iframe[name="minikube"]`);
});
it('checks if default workspace has active cluster', async () => {
await app.client.click('#current-workspace .Icon');
await app.client.waitForVisible('.WorkspaceMenu > li:first-of-type');
await app.client.click('.WorkspaceMenu > li:first-of-type');
it("checks if default workspace has active cluster", async () => {
await app.client.click("#current-workspace .Icon");
await app.client.waitForVisible(".WorkspaceMenu > li:first-of-type");
await app.client.click(".WorkspaceMenu > li:first-of-type");
await app.client.waitForVisible(".ClustersMenu .ClusterIcon.active");
});
});
@ -170,7 +167,7 @@ describe("Lens integration tests", () => {
await app.client.waitUntilTextExists("span.link-text", "Cluster");
};
describeif(ready)("cluster tests", () => {
util.describeIf(ready)("cluster tests", () => {
let clusterAdded = false;
const addCluster = async () => {
@ -190,7 +187,7 @@ describe("Lens integration tests", () => {
}
});
it('allows to add a cluster', async () => {
it("allows to add a cluster", async () => {
await addCluster();
clusterAdded = true;
});
@ -515,7 +512,7 @@ describe("Lens integration tests", () => {
}
});
it('shows default namespace', async () => {
it("shows default namespace", async () => {
expect(clusterAdded).toBe(true);
await app.client.click('a[href="/namespaces"]');
await app.client.waitUntilTextExists("div.TableCell", "default");
@ -539,7 +536,7 @@ describe("Lens integration tests", () => {
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods");
await app.client.click('a[href^="/pods"]');
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver");
await app.client.click('.Icon.new-dock-tab');
await app.client.click(".Icon.new-dock-tab");
await app.client.waitUntilTextExists("li.MenuItem.create-resource-tab", "Create resource");
await app.client.click("li.MenuItem.create-resource-tab");
await app.client.waitForVisible(".CreateResource div.ace_content");

View File

@ -6,6 +6,14 @@ const AppPaths: Partial<Record<NodeJS.Platform, string>> = {
"darwin": "./dist/mac/Lens.app/Contents/MacOS/Lens",
};
export function itIf(condition: boolean) {
return condition ? it : it.skip;
}
export function describeIf(condition: boolean) {
return condition ? describe : describe.skip;
}
export function setup(): Application {
return new Application({
path: AppPaths[process.platform], // path to electron app

View File

@ -338,6 +338,8 @@
"electron-builder": "^22.7.0",
"electron-notarize": "^0.3.0",
"eslint": "^7.7.0",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-unused-imports": "^1.0.0",
"file-loader": "^6.0.0",
"flex.box": "^3.4.4",
"fork-ts-checker-webpack-plugin": "^5.0.0",

View File

@ -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",
}

View File

@ -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");
});
});
});

View File

@ -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",

View File

@ -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";

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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);
});

View File

@ -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
}

View File

@ -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 [
[

View File

@ -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 {

View File

@ -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

View File

@ -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> {

View File

@ -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>();

View File

@ -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";

View File

@ -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;
}

View File

@ -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);

View File

@ -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";

View File

@ -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);

View File

@ -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;
});

View File

@ -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";

View File

@ -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]);
}

View File

@ -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);

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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;
});

View File

@ -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

View File

@ -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 });
});

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}));
});

View File

@ -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();
});
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 = () => {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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);
});

View File

@ -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
};
}

View File

@ -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[] = [];

View File

@ -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() {

View File

@ -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";
}

View File

@ -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();
}

View File

@ -5,11 +5,11 @@ 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] });
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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;
}

View File

@ -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";

View File

@ -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) {

View File

@ -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"
}
});
}

View File

@ -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;
}

View File

@ -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
});

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -91,7 +91,6 @@ export class TerminalApi extends WebSocketApi {
}
reconnect() {
const { reconnectDelaySeconds } = this.params;
super.reconnect();
}

View File

@ -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[]) {

View File

@ -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&apos;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&apos;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>
)}

View File

@ -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 && (

View File

@ -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")}

View File

@ -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>
);
}
}

View File

@ -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&apos;t be deleted automatically</Trans>
</p>
</div>
);

View File

@ -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&apos;t have permissions to list namespaces.</Trans></p>
<EditableList
placeholder={_i18n._("Add new namespace...")}
add={(newNamespace) => {

View File

@ -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.

View File

@ -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,7 +103,7 @@ 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>
</>
)}

View File

@ -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}>
{
clusterFeatureRegistry
.getItems()
.map((f) => (
<InstallFeature key={f.title} cluster={cluster} feature={f.feature}>
<>
<SubTitle title={f.title} />
<p><f.components.Description /></p>
</>
</InstallFeature>
);
})}
))
}
</div>
);
}

View File

@ -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> {
);
}
}

View File

@ -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> {
);
}
}

View File

@ -19,7 +19,6 @@ 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">

View File

@ -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(),

View File

@ -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() {

View File

@ -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);

View File

@ -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(),
]}

View File

@ -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(", "),

View File

@ -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";

View File

@ -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}>
renderTableContents={(crd: CustomResourceDefinition) => [
<Link key="link" to={crd.getResourceUrl()} onClick={stopPropagation}>
{crd.getResourceTitle()}
</Link>,
crd.getGroup(),
crd.getVersion(),
crd.getScope(),
crd.getAge(),
];
}}
]}
/>
);
}
}

View File

@ -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(),

Some files were not shown because too many files have changed in this diff Show More