diff --git a/.eslintrc.js b/.eslintrc.js index 63ace2611b..e50982d63a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,6 +20,7 @@ module.exports = { rules: { "indent": ["error", 2], "no-unused-vars": "off", + "semi": ["error", "always"], } }, { @@ -47,7 +48,9 @@ module.exports = { "@typescript-eslint/ban-types": "off", "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-empty-interface": "off", - "indent": ["error", 2] + "indent": ["error", 2], + "semi": "off", + "@typescript-eslint/semi": ["error"], }, }, { @@ -75,7 +78,9 @@ module.exports = { "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-empty-function": "off", - "indent": ["error", 2] + "indent": ["error", 2], + "semi": "off", + "@typescript-eslint/semi": ["error"], }, } ] diff --git a/__mocks__/electron.ts b/__mocks__/electron.ts index 08c94f0f8c..86f35c956d 100644 --- a/__mocks__/electron.ts +++ b/__mocks__/electron.ts @@ -5,7 +5,7 @@ module.exports = { getVersion: jest.fn().mockReturnValue("3.0.0"), getLocale: jest.fn().mockRejectedValue("en"), getPath: jest.fn((name: string) => { - return "tmp" + return "tmp"; }), }, remote: { diff --git a/build/build_tray_icon.ts b/build/build_tray_icon.ts index 00d09b69bc..e02d884412 100644 --- a/build/build_tray_icon.ts +++ b/build/build_tray_icon.ts @@ -1,9 +1,9 @@ // Generate tray icons from SVG to PNG + different sizes and colors (B&W) // Command: `yarn build:tray-icons` -import path from "path" +import path from "path"; import sharp from "sharp"; -import jsdom from "jsdom" -import fs from "fs-extra" +import jsdom from "jsdom"; +import fs from "fs-extra"; export async function generateTrayIcon( { @@ -14,15 +14,15 @@ export async function generateTrayIcon( pixelSize = 32, shouldUseDarkColors = false, // managed by electron.nativeTheme.shouldUseDarkColors } = {}) { - outputFilename += shouldUseDarkColors ? "_dark" : "" - dpiSuffix = dpiSuffix !== "1x" ? `@${dpiSuffix}` : "" - const pngIconDestPath = path.resolve(outputFolder, `${outputFilename}${dpiSuffix}.png`) + outputFilename += shouldUseDarkColors ? "_dark" : ""; + dpiSuffix = dpiSuffix !== "1x" ? `@${dpiSuffix}` : ""; + const pngIconDestPath = path.resolve(outputFolder, `${outputFilename}${dpiSuffix}.png`); try { // Modify .SVG colors const trayIconColor = shouldUseDarkColors ? "white" : "black"; const svgDom = await jsdom.JSDOM.fromFile(svgIconPath); const svgRoot = svgDom.window.document.body.getElementsByTagName("svg")[0]; - svgRoot.innerHTML += `` + svgRoot.innerHTML += ``; const svgIconBuffer = Buffer.from(svgRoot.outerHTML); // Resize and convert to .PNG diff --git a/build/download_helm.ts b/build/download_helm.ts index 9dddf7fcdc..7a3dc62a72 100644 --- a/build/download_helm.ts +++ b/build/download_helm.ts @@ -1,3 +1,3 @@ -import { helmCli } from "../src/main/helm/helm-cli" +import { helmCli } from "../src/main/helm/helm-cli"; -helmCli.ensureBinary() +helmCli.ensureBinary(); diff --git a/build/download_kubectl.ts b/build/download_kubectl.ts index a697552aa8..137588ff58 100644 --- a/build/download_kubectl.ts +++ b/build/download_kubectl.ts @@ -1,20 +1,20 @@ -import packageInfo from "../package.json" -import fs from "fs" -import request from "request" -import md5File from "md5-file" -import requestPromise from "request-promise-native" -import { ensureDir, pathExists } from "fs-extra" -import path from "path" +import packageInfo from "../package.json"; +import fs from "fs"; +import request from "request"; +import md5File from "md5-file"; +import requestPromise from "request-promise-native"; +import { ensureDir, pathExists } from "fs-extra"; +import path from "path"; class KubectlDownloader { - public kubectlVersion: string - protected url: string + public kubectlVersion: string; + protected url: string; protected path: string; - protected dirname: string + protected dirname: string; constructor(clusterVersion: string, platform: string, arch: string, target: string) { this.kubectlVersion = clusterVersion; - const binaryName = platform === "windows" ? "kubectl.exe" : "kubectl" + const binaryName = platform === "windows" ? "kubectl.exe" : "kubectl"; this.url = `https://storage.googleapis.com/kubernetes-release/release/v${this.kubectlVersion}/bin/${platform}/${arch}/${binaryName}`; this.dirname = path.dirname(target); this.path = target; @@ -25,83 +25,85 @@ class KubectlDownloader { method: "HEAD", uri: this.url, resolveWithFullResponse: true - }).catch((error) => { console.log(error) }) + }).catch((error) => { console.log(error); }); if (response.headers["etag"]) { - return response.headers["etag"].replace(/"/g, "") + return response.headers["etag"].replace(/"/g, ""); } - return "" + return ""; } public async checkBinary() { - const exists = await pathExists(this.path) + const exists = await pathExists(this.path); if (exists) { - const hash = md5File.sync(this.path) - const etag = await this.urlEtag() + const hash = md5File.sync(this.path); + const etag = await this.urlEtag(); if(hash == etag) { - console.log("Kubectl md5sum matches the remote etag") - return true + console.log("Kubectl md5sum matches the remote etag"); + return true; } - console.log("Kubectl md5sum " + hash + " does not match the remote etag " + etag + ", unlinking and downloading again") - await fs.promises.unlink(this.path) + console.log("Kubectl md5sum " + hash + " does not match the remote etag " + etag + ", unlinking and downloading again"); + await fs.promises.unlink(this.path); } - return false + return false; } public async downloadKubectl() { const exists = await this.checkBinary(); if(exists) { - console.log("Already exists and is valid") - return + console.log("Already exists and is valid"); + return; } - await ensureDir(path.dirname(this.path), 0o755) + await ensureDir(path.dirname(this.path), 0o755); - const file = fs.createWriteStream(this.path) - console.log(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`) + const file = fs.createWriteStream(this.path); + console.log(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`); const requestOpts: request.UriOptions & request.CoreOptions = { uri: this.url, gzip: true - } - const stream = request(requestOpts) + }; + const stream = request(requestOpts); stream.on("complete", () => { - console.log("kubectl binary download finished") - file.end(() => {}) - }) + console.log("kubectl binary download finished"); + // eslint-disable-next-line @typescript-eslint/no-empty-function + file.end(() => {}); + }); stream.on("error", (error) => { - console.log(error) - fs.unlink(this.path, () => {}) - throw(error) - }) + console.log(error); + // eslint-disable-next-line @typescript-eslint/no-empty-function + fs.unlink(this.path, () => {}); + throw(error); + }); return new Promise((resolve, reject) => { file.on("close", () => { - console.log("kubectl binary download closed") + console.log("kubectl binary download closed"); fs.chmod(this.path, 0o755, (err) => { if (err) reject(err); - }) - resolve() - }) - stream.pipe(file) - }) + }); + resolve(); + }); + stream.pipe(file); + }); } } 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') } -] +]; downloads.forEach((dlOpts) => { - console.log(dlOpts) + console.log(dlOpts); const downloader = new KubectlDownloader(downloadVersion, dlOpts.platform, dlOpts.arch, dlOpts.target); console.log("Downloading: " + JSON.stringify(dlOpts)); - downloader.downloadKubectl().then(() => downloader.checkBinary().then(() => console.log("Download complete"))) -}) + downloader.downloadKubectl().then(() => downloader.checkBinary().then(() => console.log("Download complete"))); +}); diff --git a/build/notarize.js b/build/notarize.js index 3d97b152c5..9904dccc3b 100644 --- a/build/notarize.js +++ b/build/notarize.js @@ -1,4 +1,4 @@ -const { notarize } = require('electron-notarize') +const { notarize } = require('electron-notarize'); exports.default = async function notarizing(context) { const { electronPlatformName, appOutDir } = context; diff --git a/build/set_npm_version.ts b/build/set_npm_version.ts index 70ce97416d..17d4a1ef83 100644 --- a/build/set_npm_version.ts +++ b/build/set_npm_version.ts @@ -1,9 +1,9 @@ -import * as fs from "fs" -import * as path from "path" -import packageInfo from "../src/extensions/npm/extensions/package.json" -import appInfo from "../package.json" +import * as fs from "fs"; +import * as path from "path"; +import packageInfo from "../src/extensions/npm/extensions/package.json"; +import appInfo from "../package.json"; -const packagePath = path.join(__dirname, "../src/extensions/npm/extensions/package.json") +const packagePath = path.join(__dirname, "../src/extensions/npm/extensions/package.json"); -packageInfo.version = appInfo.version -fs.writeFileSync(packagePath, JSON.stringify(packageInfo, null, 2) + "\n") +packageInfo.version = appInfo.version; +fs.writeFileSync(packagePath, JSON.stringify(packageInfo, null, 2) + "\n"); diff --git a/extensions/example-extension/page.tsx b/extensions/example-extension/page.tsx index fbb91848a9..2fe28ea49c 100644 --- a/extensions/example-extension/page.tsx +++ b/extensions/example-extension/page.tsx @@ -1,10 +1,10 @@ import { LensRendererExtension, Component } from "@k8slens/extensions"; import { CoffeeDoodle } from "react-open-doodles"; import path from "path"; -import React from "react" +import React from "react"; export function ExampleIcon(props: Component.IconProps) { - return + return ; } export class ExamplePage extends React.Component<{ extension: LensRendererExtension }> { @@ -16,7 +16,7 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens render() { const doodleStyle = { width: "200px" - } + }; return (
@@ -24,6 +24,6 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens

File: {__filename}

- ) + ); } } diff --git a/extensions/example-extension/renderer.tsx b/extensions/example-extension/renderer.tsx index 7733ec6e47..ffec687e40 100644 --- a/extensions/example-extension/renderer.tsx +++ b/extensions/example-extension/renderer.tsx @@ -1,6 +1,6 @@ import { LensRendererExtension } from "@k8slens/extensions"; -import { ExampleIcon, ExamplePage } from "./page" -import React from "react" +import { ExampleIcon, ExamplePage } from "./page"; +import React from "react"; export default class ExampleExtension extends LensRendererExtension { clusterPages = [ diff --git a/extensions/kube-object-event-status/renderer.tsx b/extensions/kube-object-event-status/renderer.tsx index d5ca828c22..6224464a56 100644 --- a/extensions/kube-object-event-status/renderer.tsx +++ b/extensions/kube-object-event-status/renderer.tsx @@ -1,5 +1,5 @@ import { LensRendererExtension, K8sApi } from "@k8slens/extensions"; -import { resolveStatus, resolveStatusForCronJobs, resolveStatusForPods } from "./src/resolver" +import { resolveStatus, resolveStatusForCronJobs, resolveStatusForPods } from "./src/resolver"; export default class EventResourceStatusRendererExtension extends LensRendererExtension { kubeObjectStatusTexts = [ diff --git a/extensions/kube-object-event-status/src/resolver.tsx b/extensions/kube-object-event-status/src/resolver.tsx index ee83293815..e3921a9cd0 100644 --- a/extensions/kube-object-event-status/src/resolver.tsx +++ b/extensions/kube-object-event-status/src/resolver.tsx @@ -1,9 +1,9 @@ import { K8sApi } from "@k8slens/extensions"; export function resolveStatus(object: K8sApi.KubeObject): K8sApi.KubeObjectStatus { - const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi) + const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi); const events = (eventStore as K8sApi.EventStore).getEventsByObject(object); - let warnings = events.filter(evt => evt.isWarning()); + const warnings = events.filter(evt => evt.isWarning()); if (!events.length || !warnings.length) { return null; } @@ -12,16 +12,16 @@ export function resolveStatus(object: K8sApi.KubeObject): K8sApi.KubeObjectStatu level: K8sApi.KubeObjectStatusLevel.WARNING, text: `${event.message}`, timestamp: event.metadata.creationTimestamp - } + }; } export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus { if (!pod.hasIssues()) { - return null + return null; } - const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi) + const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi); const events = (eventStore as K8sApi.EventStore).getEventsByObject(pod); - let warnings = events.filter(evt => evt.isWarning()); + const warnings = events.filter(evt => evt.isWarning()); if (!events.length || !warnings.length) { return null; } @@ -30,13 +30,13 @@ export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus { level: K8sApi.KubeObjectStatusLevel.WARNING, text: `${event.message}`, timestamp: event.metadata.creationTimestamp - } + }; } export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeObjectStatus { - const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi) + const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi); let events = (eventStore as K8sApi.EventStore).getEventsByObject(cronJob); - let warnings = events.filter(evt => evt.isWarning()); + const warnings = events.filter(evt => evt.isWarning()); if (cronJob.isNeverRun()) { events = events.filter(event => event.reason != "FailedNeedsStart"); } @@ -48,5 +48,5 @@ export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeOb level: K8sApi.KubeObjectStatusLevel.WARNING, text: `${event.message}`, timestamp: event.metadata.creationTimestamp - } + }; } \ No newline at end of file diff --git a/extensions/license-menu-item/main.ts b/extensions/license-menu-item/main.ts index d43cf09e96..ca84041036 100644 --- a/extensions/license-menu-item/main.ts +++ b/extensions/license-menu-item/main.ts @@ -6,7 +6,7 @@ export default class LicenseLensMainExtension extends LensMainExtension { parentId: "help", label: "License", async click() { - Util.openExternal("https://k8slens.dev/licenses/eula.md") + Util.openExternal("https://k8slens.dev/licenses/eula.md"); } } ] diff --git a/extensions/license-menu-item/webpack.config.ts b/extensions/license-menu-item/webpack.config.ts index fec13a7096..7edcb8355e 100644 --- a/extensions/license-menu-item/webpack.config.ts +++ b/extensions/license-menu-item/webpack.config.ts @@ -1,4 +1,4 @@ -import path from "path" +import path from "path"; const outputPath = path.resolve(__dirname, 'dist'); diff --git a/extensions/metrics-cluster-feature/renderer.tsx b/extensions/metrics-cluster-feature/renderer.tsx index 58565c13f5..a285328b12 100644 --- a/extensions/metrics-cluster-feature/renderer.tsx +++ b/extensions/metrics-cluster-feature/renderer.tsx @@ -1,6 +1,6 @@ -import { LensRendererExtension } from "@k8slens/extensions" -import { MetricsFeature } from "./src/metrics-feature" -import React from "react" +import { LensRendererExtension } from "@k8slens/extensions"; +import { MetricsFeature } from "./src/metrics-feature"; +import React from "react"; export default class ClusterMetricsFeatureExtension extends LensRendererExtension { clusterFeatures = [ @@ -13,8 +13,8 @@ export default class ClusterMetricsFeatureExtension extends LensRendererExtensio 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 here. - - ) + + ); } }, feature: new MetricsFeature() diff --git a/extensions/metrics-cluster-feature/src/metrics-feature.ts b/extensions/metrics-cluster-feature/src/metrics-feature.ts index b42b726c0b..777f36b35a 100644 --- a/extensions/metrics-cluster-feature/src/metrics-feature.ts +++ b/extensions/metrics-cluster-feature/src/metrics-feature.ts @@ -1,6 +1,6 @@ -import { ClusterFeature, Store, K8sApi } from "@k8slens/extensions" -import semver from "semver" -import * as path from "path" +import { ClusterFeature, Store, K8sApi } from "@k8slens/extensions"; +import semver from "semver"; +import * as path from "path"; export interface MetricsConfiguration { // Placeholder for Metrics config structure @@ -51,46 +51,46 @@ export class MetricsFeature extends ClusterFeature.Feature { async install(cluster: Store.Cluster): Promise { // Check if there are storageclasses - const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass) - const scs = await storageClassApi.list() + const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass); + const scs = await storageClassApi.list(); this.config.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' )); - super.applyResources(cluster, super.renderTemplates(path.join(__dirname, "../resources/"))) + super.applyResources(cluster, super.renderTemplates(path.join(__dirname, "../resources/"))); } async upgrade(cluster: Store.Cluster): Promise { - return this.install(cluster) + return this.install(cluster); } async updateStatus(cluster: Store.Cluster): Promise { try { - const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet) - const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"}) + const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet); + const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"}); if (prometheus?.kind) { this.status.installed = true; this.status.currentVersion = prometheus.spec.template.spec.containers[0].image.split(":")[1]; this.status.canUpgrade = semver.lt(this.status.currentVersion, this.latestVersion, true); } else { - this.status.installed = false + this.status.installed = false; } } catch(e) { if (e?.error?.code === 404) { - this.status.installed = false + this.status.installed = false; } } - return this.status + return this.status; } async uninstall(cluster: Store.Cluster): Promise { - const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace) - const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding) - const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole) + const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace); + const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding); + const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole); - await namespaceApi.delete({name: "lens-metrics"}) - await clusterRoleBindingApi.delete({name: "lens-prometheus"}) - await clusterRoleApi.delete({name: "lens-prometheus"}) } + await namespaceApi.delete({name: "lens-metrics"}); + await clusterRoleBindingApi.delete({name: "lens-prometheus"}); + await clusterRoleApi.delete({name: "lens-prometheus"}); } } diff --git a/extensions/node-menu/renderer.tsx b/extensions/node-menu/renderer.tsx index db8232a518..ebe6cf46ce 100644 --- a/extensions/node-menu/renderer.tsx +++ b/extensions/node-menu/renderer.tsx @@ -1,6 +1,6 @@ import { LensRendererExtension } from "@k8slens/extensions"; -import React from "react" -import { NodeMenu, NodeMenuProps } from "./src/node-menu" +import React from "react"; +import { NodeMenu, NodeMenuProps } from "./src/node-menu"; export default class NodeMenuRendererExtension extends LensRendererExtension { kubeObjectMenuItems = [ diff --git a/extensions/node-menu/src/node-menu.tsx b/extensions/node-menu/src/node-menu.tsx index 8c7466694e..7284518ac4 100644 --- a/extensions/node-menu/src/node-menu.tsx +++ b/extensions/node-menu/src/node-menu.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Component, K8sApi, Navigation} from "@k8slens/extensions" +import { Component, K8sApi, Navigation} from "@k8slens/extensions"; export interface NodeMenuProps extends Component.KubeObjectMenuProps { } @@ -15,7 +15,7 @@ export function NodeMenu(props: NodeMenuProps) { newTab: true, }); Navigation.hideDetails(); - } + }; const shell = () => { Component.createTerminalTab({ @@ -23,15 +23,15 @@ export function NodeMenu(props: NodeMenuProps) { node: nodeName, }); Navigation.hideDetails(); - } + }; const cordon = () => { sendToTerminal(`kubectl cordon ${nodeName}`); - } + }; const unCordon = () => { - sendToTerminal(`kubectl uncordon ${nodeName}`) - } + sendToTerminal(`kubectl uncordon ${nodeName}`); + }; const drain = () => { const command = `kubectl drain ${nodeName} --delete-local-data --ignore-daemonsets --force`; @@ -43,8 +43,8 @@ export function NodeMenu(props: NodeMenuProps) { Are you sure you want to drain {nodeName}?

), - }) - } + }); + }; return ( <> diff --git a/extensions/pod-menu/renderer.tsx b/extensions/pod-menu/renderer.tsx index 30898da806..e13195ee68 100644 --- a/extensions/pod-menu/renderer.tsx +++ b/extensions/pod-menu/renderer.tsx @@ -1,7 +1,7 @@ import { LensRendererExtension } from "@k8slens/extensions"; -import { PodShellMenu, PodShellMenuProps } from "./src/shell-menu" -import { PodLogsMenu, PodLogsMenuProps } from "./src/logs-menu" -import React from "react" +import { PodShellMenu, PodShellMenuProps } from "./src/shell-menu"; +import { PodLogsMenu, PodLogsMenuProps } from "./src/logs-menu"; +import React from "react"; export default class PodMenuRendererExtension extends LensRendererExtension { kubeObjectMenuItems = [ diff --git a/extensions/pod-menu/src/logs-menu.tsx b/extensions/pod-menu/src/logs-menu.tsx index a1a6dba834..2556691ca2 100644 --- a/extensions/pod-menu/src/logs-menu.tsx +++ b/extensions/pod-menu/src/logs-menu.tsx @@ -19,7 +19,7 @@ export class PodLogsMenu extends React.Component { } render() { - const { object: pod, toolbar } = this.props + const { object: pod, toolbar } = this.props; const containers = pod.getAllContainers(); const statuses = pod.getContainerStatuses(); if (!containers.length) return null; @@ -33,25 +33,25 @@ export class PodLogsMenu extends React.Component { { containers.map(container => { - const { name } = container + const { name } = container; const status = statuses.find(status => status.name === name); const brick = status ? ( - ) : null + ) : null; return ( this.showLogs(container))} className="flex align-center"> {brick} {name} - ) + ); }) } )} - ) + ); } } diff --git a/extensions/pod-menu/src/shell-menu.tsx b/extensions/pod-menu/src/shell-menu.tsx index 02e248810b..d33db02d8c 100644 --- a/extensions/pod-menu/src/shell-menu.tsx +++ b/extensions/pod-menu/src/shell-menu.tsx @@ -9,16 +9,16 @@ export interface PodShellMenuProps extends Component.KubeObjectMenuProps { async execShell(container?: string) { Navigation.hideDetails(); - const { object: pod } = this.props - const containerParam = container ? `-c ${container}` : "" - let command = `kubectl exec -i -t -n ${pod.getNs()} ${pod.getName()} ${containerParam} "--"` + const { object: pod } = this.props; + const containerParam = container ? `-c ${container}` : ""; + let command = `kubectl exec -i -t -n ${pod.getNs()} ${pod.getName()} ${containerParam} "--"`; if (window.navigator.platform !== "Win32") { - command = `exec ${command}` + command = `exec ${command}`; } if (pod.getSelectedNodeOs() === "windows") { - command = `${command} powershell` + command = `${command} powershell`; } else { - command = `${command} sh -c "clear; (bash || ash || sh)"` + command = `${command} sh -c "clear; (bash || ash || sh)"`; } const shell = Component.createTerminalTab({ @@ -32,7 +32,7 @@ export class PodShellMenu extends React.Component { } render() { - const { object, toolbar } = this.props + const { object, toolbar } = this.props; const containers = object.getRunningContainers(); if (!containers.length) return null; return ( @@ -51,13 +51,13 @@ export class PodShellMenu extends React.Component { {name} - ) + ); }) } )} - ) + ); } } diff --git a/extensions/support-page/src/support.tsx b/extensions/support-page/src/support.tsx index fbdf54d9eb..e947eb0f60 100644 --- a/extensions/support-page/src/support.tsx +++ b/extensions/support-page/src/support.tsx @@ -1,8 +1,8 @@ // TODO: support localization / figure out how to extract / consume i18n strings -import "./support.scss" -import React from "react" -import { observer } from "mobx-react" +import "./support.scss"; +import React from "react"; +import { observer } from "mobx-react"; import { App, Component } from "@k8slens/extensions"; @observer diff --git a/extensions/support-page/webpack.config.ts b/extensions/support-page/webpack.config.ts index 45ca3d2a10..ca709e6ee0 100644 --- a/extensions/support-page/webpack.config.ts +++ b/extensions/support-page/webpack.config.ts @@ -1,4 +1,4 @@ -import path from "path" +import path from "path"; const outputPath = path.resolve(__dirname, 'dist'); diff --git a/extensions/telemetry/main.ts b/extensions/telemetry/main.ts index aef51ff647..0b6b13f568 100644 --- a/extensions/telemetry/main.ts +++ b/extensions/telemetry/main.ts @@ -1,18 +1,18 @@ import { LensMainExtension } from "@k8slens/extensions"; -import { telemetryPreferencesStore } from "./src/telemetry-preferences-store" +import { telemetryPreferencesStore } from "./src/telemetry-preferences-store"; import { tracker } from "./src/tracker"; export default class TelemetryMainExtension extends LensMainExtension { async onActivate() { - console.log("telemetry main extension activated") - tracker.start() - tracker.reportPeriodically() - await telemetryPreferencesStore.loadExtension(this) + console.log("telemetry main extension activated"); + tracker.start(); + tracker.reportPeriodically(); + await telemetryPreferencesStore.loadExtension(this); } onDeactivate() { - tracker.stop() - console.log("telemetry main extension deactivated") + tracker.stop(); + console.log("telemetry main extension deactivated"); } } diff --git a/extensions/telemetry/renderer.tsx b/extensions/telemetry/renderer.tsx index 04057386bf..1078d18f4c 100644 --- a/extensions/telemetry/renderer.tsx +++ b/extensions/telemetry/renderer.tsx @@ -1,8 +1,8 @@ import { LensRendererExtension } from "@k8slens/extensions"; -import { telemetryPreferencesStore } from "./src/telemetry-preferences-store" -import { TelemetryPreferenceHint, TelemetryPreferenceInput } from "./src/telemetry-preference" -import { tracker } from "./src/tracker" -import React from "react" +import { telemetryPreferencesStore } from "./src/telemetry-preferences-store"; +import { TelemetryPreferenceHint, TelemetryPreferenceInput } from "./src/telemetry-preference"; +import { tracker } from "./src/tracker"; +import React from "react"; export default class TelemetryRendererExtension extends LensRendererExtension { appPreferences = [ @@ -16,8 +16,8 @@ export default class TelemetryRendererExtension extends LensRendererExtension { ]; async onActivate() { - console.log("telemetry extension activated") - tracker.start() - await telemetryPreferencesStore.loadExtension(this) + console.log("telemetry extension activated"); + tracker.start(); + await telemetryPreferencesStore.loadExtension(this); } } diff --git a/extensions/telemetry/src/telemetry-preference.tsx b/extensions/telemetry/src/telemetry-preference.tsx index 122d722a81..f96ed43fb8 100644 --- a/extensions/telemetry/src/telemetry-preference.tsx +++ b/extensions/telemetry/src/telemetry-preference.tsx @@ -1,19 +1,19 @@ -import { Component } from "@k8slens/extensions" -import React from "react" +import { Component } from "@k8slens/extensions"; +import React from "react"; import { observer } from "mobx-react"; -import { TelemetryPreferencesStore } from "./telemetry-preferences-store" +import { TelemetryPreferencesStore } from "./telemetry-preferences-store"; @observer export class TelemetryPreferenceInput extends React.Component<{telemetry: TelemetryPreferencesStore}, {}> { render() { - const { telemetry } = this.props + const { telemetry } = this.props; return ( { telemetry.enabled = v; }} /> - ) + ); } } @@ -21,6 +21,6 @@ export class TelemetryPreferenceHint extends React.Component { render() { return ( Telemetry & usage data is collected to continuously improve the Lens experience. - ) + ); } } diff --git a/extensions/telemetry/src/telemetry-preferences-store.ts b/extensions/telemetry/src/telemetry-preferences-store.ts index e29b0ff461..e20ef1ede8 100644 --- a/extensions/telemetry/src/telemetry-preferences-store.ts +++ b/extensions/telemetry/src/telemetry-preferences-store.ts @@ -1,5 +1,5 @@ import { Store } from "@k8slens/extensions"; -import { toJS } from "mobx" +import { toJS } from "mobx"; export type TelemetryPreferencesModel = { enabled: boolean; @@ -14,11 +14,11 @@ export class TelemetryPreferencesStore extends Store.ExtensionStore() +export const telemetryPreferencesStore = TelemetryPreferencesStore.getInstance(); diff --git a/extensions/telemetry/src/tracker.ts b/extensions/telemetry/src/tracker.ts index f2d3c6c918..9837f4a98b 100644 --- a/extensions/telemetry/src/tracker.ts +++ b/extensions/telemetry/src/tracker.ts @@ -1,8 +1,8 @@ -import { EventBus, Util, Store, App } from "@k8slens/extensions" -import ua from "universal-analytics" -import Analytics from "analytics-node" -import { machineIdSync } from "node-machine-id" -import { telemetryPreferencesStore } from "./telemetry-preferences-store" +import { EventBus, Util, Store, App } from "@k8slens/extensions"; +import ua from "universal-analytics"; +import Analytics from "analytics-node"; +import { machineIdSync } from "node-machine-id"; +import { telemetryPreferencesStore } from "./telemetry-preferences-store"; export class Tracker extends Util.Singleton { static readonly GA_ID = "UA-159377374-1" @@ -23,69 +23,69 @@ export class Tracker extends Util.Singleton { private constructor() { super(); - this.anonymousId = machineIdSync() - this.os = this.resolveOS() - this.userAgent = `Lens ${App.version} (${this.os})` + this.anonymousId = machineIdSync(); + this.os = this.resolveOS(); + this.userAgent = `Lens ${App.version} (${this.os})`; try { - this.visitor = ua(Tracker.GA_ID, this.anonymousId, { strictCidFormat: false }) + this.visitor = ua(Tracker.GA_ID, this.anonymousId, { strictCidFormat: false }); } catch (error) { - this.visitor = ua(Tracker.GA_ID) + this.visitor = ua(Tracker.GA_ID); } - this.analytics = new Analytics(Tracker.SEGMENT_KEY, { flushAt: 1 }) - this.visitor.set("dl", "https://telemetry.k8slens.dev") - this.visitor.set("ua", this.userAgent) + this.analytics = new Analytics(Tracker.SEGMENT_KEY, { flushAt: 1 }); + this.visitor.set("dl", "https://telemetry.k8slens.dev"); + this.visitor.set("ua", this.userAgent); } start() { - if (this.started === true) { return } + if (this.started === true) { return; } - this.started = true + this.started = true; const handler = (ev: EventBus.AppEvent) => { - this.event(ev.name, ev.action, ev.params) - } - this.eventHandlers.push(handler) - EventBus.appEventBus.addListener(handler) + this.event(ev.name, ev.action, ev.params); + }; + this.eventHandlers.push(handler); + EventBus.appEventBus.addListener(handler); } reportPeriodically() { this.reportInterval = setInterval(() => { - this.reportData() - }, 60 * 60 * 1000) // report every 1h + this.reportData(); + }, 60 * 60 * 1000); // report every 1h } stop() { - if (!this.started) { return } + if (!this.started) { return; } - this.started = false + this.started = false; for (const handler of this.eventHandlers) { - EventBus.appEventBus.removeListener(handler) + EventBus.appEventBus.removeListener(handler); } if (this.reportInterval) { - clearInterval(this.reportInterval) + clearInterval(this.reportInterval); } } protected async isTelemetryAllowed(): Promise { - return telemetryPreferencesStore.enabled + return telemetryPreferencesStore.enabled; } protected reportData() { - const clustersList = Store.clusterStore.enabledClustersList + const clustersList = Store.clusterStore.enabledClustersList; this.event("generic-data", "report", { appVersion: App.version, os: this.os, clustersCount: clustersList.length, workspacesCount: Store.workspaceStore.enabledWorkspacesList.length - }) + }); clustersList.forEach((cluster) => { - if (!cluster?.metadata.lastSeen) { return } - this.reportClusterData(cluster) - }) + if (!cluster?.metadata.lastSeen) { return; } + this.reportClusterData(cluster); + }); } protected reportClusterData(cluster: Store.ClusterModel) { @@ -96,26 +96,26 @@ export class Tracker extends Util.Singleton { distribution: cluster.metadata.distribution, nodesCount: cluster.metadata.nodes, lastSeen: cluster.metadata.lastSeen - }) + }); } protected resolveOS() { - let os = "" + let os = ""; if (App.isMac) { - os = "MacOS" + os = "MacOS"; } else if(App.isWindows) { - os = "Windows" + os = "Windows"; } else if (App.isLinux) { - os = "Linux" + os = "Linux"; if (App.isSnap) { - os += "; Snap" + os += "; Snap"; } else { - os += "; AppImage" + os += "; AppImage"; } } else { - os = "Unknown" + os = "Unknown"; } - return os + return os; } protected async event(eventCategory: string, eventAction: string, otherParams = {}) { @@ -128,7 +128,7 @@ export class Tracker extends Util.Singleton { ec: eventCategory, ea: eventAction, ...otherParams, - }).send() + }).send(); this.analytics.track({ anonymousId: this.anonymousId, @@ -141,9 +141,9 @@ export class Tracker extends Util.Singleton { ...otherParams, }, - }) + }); } catch (err) { - console.error(`Failed to track "${eventCategory}:${eventAction}"`, err) + console.error(`Failed to track "${eventCategory}:${eventAction}"`, err); } } } diff --git a/integration/__tests__/app.tests.ts b/integration/__tests__/app.tests.ts index 8845ae91a8..ace852904d 100644 --- a/integration/__tests__/app.tests.ts +++ b/integration/__tests__/app.tests.ts @@ -4,159 +4,159 @@ TEST_NAMESPACE namespace. This is done to minimize destructive impact of the cluster tests on an existing minikube cluster and vice versa. */ -import { Application } from "spectron" -import * as util from "../helpers/utils" -import { spawnSync } from "child_process" +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 +const describeif = (condition: boolean) => condition ? describe : describe.skip; +const itif = (condition: boolean) => condition ? it : it.skip; -jest.setTimeout(60000) +jest.setTimeout(60000); // FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below) describe("Lens integration tests", () => { - const TEST_NAMESPACE = "integration-tests" + const TEST_NAMESPACE = "integration-tests"; - const BACKSPACE = "\uE003" - let app: Application + const BACKSPACE = "\uE003"; + let app: Application; const appStart = async () => { - app = util.setup() - await app.start() + app = util.setup(); + await app.start(); // Wait for splash screen to be closed while (await app.client.getWindowCount() > 1); - await app.client.windowByIndex(0) - await app.client.waitUntilWindowLoaded() - } + await app.client.windowByIndex(0); + await app.client.waitUntilWindowLoaded(); + }; const clickWhatsNew = async (app: Application) => { - await app.client.waitUntilTextExists("h1", "What's new?") - await app.client.click("button.primary") - await app.client.waitUntilTextExists("h1", "Welcome") - } + await app.client.waitUntilTextExists("h1", "What's new?"); + await app.client.click("button.primary"); + await app.client.waitUntilTextExists("h1", "Welcome"); + }; describe("app start", () => { - beforeAll(appStart, 20000) + beforeAll(appStart, 20000); afterAll(async () => { if (app && app.isRunning()) { - return util.tearDown(app) + return util.tearDown(app); } - }) + }); it('shows "whats new"', async () => { - await clickWhatsNew(app) - }) + await clickWhatsNew(app); + }); it('shows "add cluster"', async () => { - await app.electron.ipcRenderer.send('test-menu-item-click', "File", "Add Cluster") - await app.client.waitUntilTextExists("h2", "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 () => { - let appName: string = process.platform === "darwin" ? "Lens" : "File" - await app.electron.ipcRenderer.send('test-menu-item-click', appName, "Preferences") - await app.client.waitUntilTextExists("h2", "Preferences") - }) + const appName: string = process.platform === "darwin" ? "Lens" : "File"; + await app.electron.ipcRenderer.send('test-menu-item-click', appName, "Preferences"); + await app.client.waitUntilTextExists("h2", "Preferences"); + }); it('ensures helm repos', async () => { - await app.client.waitUntilTextExists("div.repos #message-stable", "stable") // wait for the helm-cli to fetch the stable 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) - }) - }) + await app.client.waitUntilTextExists("div.repos #message-stable", "stable"); // wait for the helm-cli to fetch the stable 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) + }); + }); 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'); + }); + }); const minikubeReady = (): boolean => { // determine if minikube is running - let status = spawnSync("minikube status", { shell: true }) + let status = spawnSync("minikube status", { shell: true }); if (status.status !== 0) { - console.warn("minikube not running") - return false + console.warn("minikube not running"); + return false; } // Remove TEST_NAMESPACE if it already exists - status = spawnSync(`minikube kubectl -- get namespace ${TEST_NAMESPACE}`, { shell: true }) + status = spawnSync(`minikube kubectl -- get namespace ${TEST_NAMESPACE}`, { shell: true }); if (status.status === 0) { - console.warn(`Removing existing ${TEST_NAMESPACE} namespace`) - status = spawnSync(`minikube kubectl -- delete namespace ${TEST_NAMESPACE}`, { shell: true }) + console.warn(`Removing existing ${TEST_NAMESPACE} namespace`); + status = spawnSync(`minikube kubectl -- delete namespace ${TEST_NAMESPACE}`, { shell: true }); if (status.status !== 0) { - console.warn(`Error removing ${TEST_NAMESPACE} namespace: ${status.stderr.toString()}`) - return false + console.warn(`Error removing ${TEST_NAMESPACE} namespace: ${status.stderr.toString()}`); + return false; } - console.log(status.stdout.toString()) + console.log(status.stdout.toString()); } - return true - } - const ready = minikubeReady() + return true; + }; + const ready = minikubeReady(); const addMinikubeCluster = async (app: Application) => { - await app.client.click("div.add-cluster") - await app.client.waitUntilTextExists("div", "Select kubeconfig file") - await app.client.click("div.Select__control") // show the context drop-down list - await app.client.waitUntilTextExists("div", "minikube") + await app.client.click("div.add-cluster"); + await app.client.waitUntilTextExists("div", "Select kubeconfig file"); + await app.client.click("div.Select__control"); // show the context drop-down list + await app.client.waitUntilTextExists("div", "minikube"); if (!await app.client.$("button.primary").isEnabled()) { - await app.client.click("div.minikube") // select minikube context + await app.client.click("div.minikube"); // select minikube context } // else the only context, which must be 'minikube', is automatically selected - await app.client.click("div.Select__control") // hide the context drop-down list (it might be obscuring the Add cluster(s) button) - await app.client.click("button.primary") // add minikube cluster - } + await app.client.click("div.Select__control"); // hide the context drop-down list (it might be obscuring the Add cluster(s) button) + await app.client.click("button.primary"); // add minikube cluster + }; const waitForMinikubeDashboard = async (app: Application) => { - await app.client.waitUntilTextExists("pre.kube-auth-out", "Authentication proxy started") - await app.client.waitForExist(`iframe[name="minikube"]`) - await app.client.frame("minikube") - await app.client.waitUntilTextExists("span.link-text", "Cluster") - } + await app.client.waitUntilTextExists("pre.kube-auth-out", "Authentication proxy started"); + await app.client.waitForExist(`iframe[name="minikube"]`); + await app.client.frame("minikube"); + await app.client.waitUntilTextExists("span.link-text", "Cluster"); + }; describeif(ready)("cluster tests", () => { - let clusterAdded = false + let clusterAdded = false; const addCluster = async () => { - await clickWhatsNew(app) - await addMinikubeCluster(app) - await waitForMinikubeDashboard(app) - await app.client.click('a[href="/nodes"]') - await app.client.waitUntilTextExists("div.TableCell", "Ready") - } + await clickWhatsNew(app); + await addMinikubeCluster(app); + await waitForMinikubeDashboard(app); + await app.client.click('a[href="/nodes"]'); + await app.client.waitUntilTextExists("div.TableCell", "Ready"); + }; describe("cluster add", () => { - beforeAll(appStart, 20000) + beforeAll(appStart, 20000); afterAll(async () => { if (app && app.isRunning()) { - return util.tearDown(app) + return util.tearDown(app); } - }) + }); it('allows to add a cluster', async () => { - await addCluster() - clusterAdded = true - }) - }) + await addCluster(); + clusterAdded = true; + }); + }); const appStartAddCluster = async () => { if (clusterAdded) { - await appStart() - await addCluster() + await appStart(); + await addCluster(); } - } + }; describe("cluster pages", () => { - beforeAll(appStartAddCluster, 40000) + beforeAll(appStartAddCluster, 40000); afterAll(async () => { if (app && app.isRunning()) { - return util.tearDown(app) + return util.tearDown(app); } - }) + }); const tests: { drawer?: string @@ -394,119 +394,119 @@ describe("Lens integration tests", () => { tests.forEach(({ drawer = "", drawerId = "", pages }) => { if (drawer !== "") { it(`shows ${drawer} drawer`, async () => { - expect(clusterAdded).toBe(true) - await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`) - await app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name) - }) + expect(clusterAdded).toBe(true); + await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`); + await app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name); + }); } pages.forEach(({ name, href, expectedSelector, expectedText }) => { it(`shows ${drawer}->${name} page`, async () => { - expect(clusterAdded).toBe(true) - await app.client.click(`a[href^="/${href}"]`) - await app.client.waitUntilTextExists(expectedSelector, expectedText) - }) - }) + expect(clusterAdded).toBe(true); + await app.client.click(`a[href^="/${href}"]`); + await app.client.waitUntilTextExists(expectedSelector, expectedText); + }); + }); if (drawer !== "") { // hide the drawer it(`hides ${drawer} drawer`, async () => { - expect(clusterAdded).toBe(true) - await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`) - await expect(app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name, 100)).rejects.toThrow() - }) + expect(clusterAdded).toBe(true); + await app.client.click(`.sidebar-nav [data-test-id="${drawerId}"] span.link-text`); + await expect(app.client.waitUntilTextExists(`a[href^="/${pages[0].href}"]`, pages[0].name, 100)).rejects.toThrow(); + }); } - }) - }) + }); + }); describe("viewing pod logs", () => { - beforeEach(appStartAddCluster, 40000) + beforeEach(appStartAddCluster, 40000); afterEach(async () => { if (app && app.isRunning()) { - return util.tearDown(app) + return util.tearDown(app); } - }) + }); it(`shows a logs for a pod`, async () => { - expect(clusterAdded).toBe(true) + expect(clusterAdded).toBe(true); // Go to Pods page - await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text") - 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(".sidebar-nav [data-test-id='workloads'] span.link-text"); + await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods"); + await app.client.click('a[href^="/pods"]'); + await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver"); // Open logs tab in dock - await app.client.click(".list .TableRow:first-child") - await app.client.waitForVisible(".Drawer") - await app.client.click(".drawer-title .Menu li:nth-child(2)") + await app.client.click(".list .TableRow:first-child"); + await app.client.waitForVisible(".Drawer"); + await app.client.click(".drawer-title .Menu li:nth-child(2)"); // Check if controls are available - await app.client.waitForVisible(".PodLogs .VirtualList") - await app.client.waitForVisible(".PodLogControls") - await app.client.waitForVisible(".PodLogControls .SearchInput") - await app.client.waitForVisible(".PodLogControls .SearchInput input") + await app.client.waitForVisible(".PodLogs .VirtualList"); + await app.client.waitForVisible(".PodLogControls"); + await app.client.waitForVisible(".PodLogControls .SearchInput"); + await app.client.waitForVisible(".PodLogControls .SearchInput input"); // Search for semicolon - await app.client.keys(":") - await app.client.waitForVisible(".PodLogs .list span.active") + await app.client.keys(":"); + await app.client.waitForVisible(".PodLogs .list span.active"); // Click through controls - await app.client.click(".PodLogControls .timestamps-icon") - await app.client.click(".PodLogControls .undo-icon") - }) - }) + await app.client.click(".PodLogControls .timestamps-icon"); + await app.client.click(".PodLogControls .undo-icon"); + }); + }); describe("cluster operations", () => { - beforeEach(appStartAddCluster, 40000) + beforeEach(appStartAddCluster, 40000); afterEach(async () => { if (app && app.isRunning()) { - return util.tearDown(app) + return util.tearDown(app); } - }) + }); it('shows default namespace', async () => { - expect(clusterAdded).toBe(true) - await app.client.click('a[href="/namespaces"]') - await app.client.waitUntilTextExists("div.TableCell", "default") - await app.client.waitUntilTextExists("div.TableCell", "kube-system") - }) + expect(clusterAdded).toBe(true); + await app.client.click('a[href="/namespaces"]'); + await app.client.waitUntilTextExists("div.TableCell", "default"); + await app.client.waitUntilTextExists("div.TableCell", "kube-system"); + }); it(`creates ${TEST_NAMESPACE} namespace`, async () => { - expect(clusterAdded).toBe(true) - await app.client.click('a[href="/namespaces"]') - await app.client.waitUntilTextExists("div.TableCell", "default") - await app.client.waitUntilTextExists("div.TableCell", "kube-system") - await app.client.click("button.add-button") - await app.client.waitUntilTextExists("div.AddNamespaceDialog", "Create Namespace") - await app.client.keys(`${TEST_NAMESPACE}\n`) - await app.client.waitForExist(`.name=${TEST_NAMESPACE}`) - }) + expect(clusterAdded).toBe(true); + await app.client.click('a[href="/namespaces"]'); + await app.client.waitUntilTextExists("div.TableCell", "default"); + await app.client.waitUntilTextExists("div.TableCell", "kube-system"); + await app.client.click("button.add-button"); + await app.client.waitUntilTextExists("div.AddNamespaceDialog", "Create Namespace"); + await app.client.keys(`${TEST_NAMESPACE}\n`); + await app.client.waitForExist(`.name=${TEST_NAMESPACE}`); + }); it(`creates a pod in ${TEST_NAMESPACE} namespace`, async () => { - expect(clusterAdded).toBe(true) - await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text") - 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.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") + expect(clusterAdded).toBe(true); + await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text"); + 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.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"); // Write pod manifest to editor - await app.client.keys("apiVersion: v1\n") - await app.client.keys("kind: Pod\n") - await app.client.keys("metadata:\n") - await app.client.keys(" name: nginx-create-pod-test\n") - await app.client.keys(`namespace: ${TEST_NAMESPACE}\n`) - await app.client.keys(BACKSPACE + "spec:\n") - await app.client.keys(" containers:\n") - await app.client.keys("- name: nginx-create-pod-test\n") - await app.client.keys(" image: nginx:alpine\n") + await app.client.keys("apiVersion: v1\n"); + await app.client.keys("kind: Pod\n"); + await app.client.keys("metadata:\n"); + await app.client.keys(" name: nginx-create-pod-test\n"); + await app.client.keys(`namespace: ${TEST_NAMESPACE}\n`); + await app.client.keys(BACKSPACE + "spec:\n"); + await app.client.keys(" containers:\n"); + await app.client.keys("- name: nginx-create-pod-test\n"); + await app.client.keys(" image: nginx:alpine\n"); // Create deployment - await app.client.waitForEnabled("button.Button=Create & Close") - await app.client.click("button.Button=Create & Close") + await app.client.waitForEnabled("button.Button=Create & Close"); + await app.client.click("button.Button=Create & Close"); // Wait until first bits of pod appears on dashboard - await app.client.waitForExist(".name=nginx-create-pod-test") + await app.client.waitForExist(".name=nginx-create-pod-test"); // Open pod details - await app.client.click(".name=nginx-create-pod-test") - await app.client.waitUntilTextExists("div.drawer-title-text", "Pod: nginx-create-pod-test") - }) - }) - }) -}) + await app.client.click(".name=nginx-create-pod-test"); + await app.client.waitUntilTextExists("div.drawer-title-text", "Pod: nginx-create-pod-test"); + }); + }); + }); +}); diff --git a/integration/helpers/utils.ts b/integration/helpers/utils.ts index 65ea9a1a78..32b7bece35 100644 --- a/integration/helpers/utils.ts +++ b/integration/helpers/utils.ts @@ -4,7 +4,7 @@ const AppPaths: Partial> = { "win32": "./dist/win-unpacked/Lens.exe", "linux": "./dist/linux-unpacked/kontena-lens", "darwin": "./dist/mac/Lens.app/Contents/MacOS/Lens", -} +}; export function setup(): Application { return new Application({ @@ -16,16 +16,16 @@ export function setup(): Application { env: { CICD: "true" } - }) + }); } export async function tearDown(app: Application) { - let mpid: any = app.mainProcess.pid - let pid = await mpid() - await app.stop() + const mpid: any = app.mainProcess.pid; + const pid = await mpid(); + await app.stop(); try { process.kill(pid, "SIGKILL"); } catch (e) { - console.error(e) + console.error(e); } } diff --git a/package.json b/package.json index ea3f76cdc3..49c7f58bf5 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "download:kubectl": "yarn run ts-node build/download_kubectl.ts", "download:helm": "yarn run ts-node build/download_helm.ts", "build:tray-icons": "yarn run ts-node build/build_tray_icon.ts", - "lint": "yarn run eslint $@ --ext js,ts,tsx --max-warnings=0 src/", + "lint": "yarn run eslint $@ --ext js,ts,tsx --max-warnings=0 src/ integration/ __mocks__/ build/", + "lint:fix": "yarn run lint --fix", "mkdocs-serve-local": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest", "typedocs-extensions-api": "yarn run typedoc --ignoreCompilerErrors --readme docs/extensions/typedoc-readme.md.tpl --name @k8slens/extensions --out docs/extensions/api --mode library --excludePrivate --hideBreadcrumbs --includes src/ src/extensions/extension-api.ts" }, diff --git a/src/common/__tests__/cluster-store.test.ts b/src/common/__tests__/cluster-store.test.ts index 8c911298cc..693c2e352c 100644 --- a/src/common/__tests__/cluster-store.test.ts +++ b/src/common/__tests__/cluster-store.test.ts @@ -5,9 +5,9 @@ import { Cluster } from "../../main/cluster"; import { ClusterStore } from "../cluster-store"; import { workspaceStore } from "../workspace-store"; -const testDataIcon = fs.readFileSync("test-data/cluster-store-migration-icon.png") +const testDataIcon = fs.readFileSync("test-data/cluster-store-migration-icon.png"); -console.log("") // fix bug +console.log(""); // fix bug let clusterStore: ClusterStore; @@ -18,15 +18,15 @@ describe("empty config", () => { 'tmp': { 'lens-cluster-store.json': JSON.stringify({}) } - } + }; mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); describe("with foo cluster added", () => { beforeEach(() => { @@ -43,30 +43,30 @@ describe("empty config", () => { workspace: workspaceStore.currentWorkspaceId }) ); - }) + }); it("adds new cluster to store", async () => { const storedCluster = clusterStore.getById("foo"); expect(storedCluster.id).toBe("foo"); expect(storedCluster.preferences.terminalCWD).toBe("/tmp"); expect(storedCluster.preferences.icon).toBe("data:image/jpeg;base64, iVBORw0KGgoAAAANSUhEUgAAA1wAAAKoCAYAAABjkf5"); - }) + }); it("adds cluster to default workspace", () => { const storedCluster = clusterStore.getById("foo"); expect(storedCluster.workspace).toBe("default"); - }) + }); it("removes cluster from store", async () => { await clusterStore.removeById("foo"); expect(clusterStore.getById("foo")).toBeUndefined(); - }) + }); it("sets active cluster", () => { clusterStore.setActive("foo"); expect(clusterStore.active.id).toBe("foo"); - }) - }) + }); + }); describe("with prod and dev clusters added", () => { beforeEach(() => { @@ -89,8 +89,8 @@ describe("empty config", () => { kubeConfigPath: ClusterStore.embedCustomKubeConfig("dev", "fancy config"), workspace: "workstation" }) - ) - }) + ); + }); it("check if store can contain multiple clusters", () => { expect(clusterStore.hasClusters()).toBeTruthy(); @@ -104,42 +104,42 @@ describe("empty config", () => { expect(wsClusters.length).toBe(2); expect(wsClusters[0].id).toBe("prod"); expect(wsClusters[1].id).toBe("dev"); - }) + }); it("check if cluster's kubeconfig file saved", () => { const file = ClusterStore.embedCustomKubeConfig("boo", "kubeconfig"); expect(fs.readFileSync(file, "utf8")).toBe("kubeconfig"); - }) + }); it("check if reorderring works for same from and to", () => { - clusterStore.swapIconOrders("workstation", 1, 1) + clusterStore.swapIconOrders("workstation", 1, 1); const clusters = clusterStore.getByWorkspaceId("workstation"); - expect(clusters[0].id).toBe("prod") - expect(clusters[0].preferences.iconOrder).toBe(0) - expect(clusters[1].id).toBe("dev") - expect(clusters[1].preferences.iconOrder).toBe(1) - }) + expect(clusters[0].id).toBe("prod"); + expect(clusters[0].preferences.iconOrder).toBe(0); + expect(clusters[1].id).toBe("dev"); + expect(clusters[1].preferences.iconOrder).toBe(1); + }); it("check if reorderring works for different from and to", () => { - clusterStore.swapIconOrders("workstation", 0, 1) + clusterStore.swapIconOrders("workstation", 0, 1); const clusters = clusterStore.getByWorkspaceId("workstation"); - expect(clusters[0].id).toBe("dev") - expect(clusters[0].preferences.iconOrder).toBe(0) - expect(clusters[1].id).toBe("prod") - expect(clusters[1].preferences.iconOrder).toBe(1) - }) + expect(clusters[0].id).toBe("dev"); + expect(clusters[0].preferences.iconOrder).toBe(0); + expect(clusters[1].id).toBe("prod"); + expect(clusters[1].preferences.iconOrder).toBe(1); + }); it("check if after icon reordering, changing workspaces still works", () => { - clusterStore.swapIconOrders("workstation", 1, 1) - clusterStore.getById("prod").workspace = "default" + clusterStore.swapIconOrders("workstation", 1, 1); + clusterStore.getById("prod").workspace = "default"; expect(clusterStore.getByWorkspaceId("workstation").length).toBe(1); expect(clusterStore.getByWorkspaceId("default").length).toBe(1); - }) - }) -}) + }); + }); +}); describe("config with existing clusters", () => { beforeEach(() => { @@ -176,21 +176,21 @@ describe("config with existing clusters", () => { ] }) } - } + }; mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); it("allows to retrieve a cluster", () => { 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'); @@ -198,18 +198,18 @@ describe("config with existing clusters", () => { expect(storedCluster).toBeTruthy(); 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.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'); + }); +}); describe("pre 2.0 config with an existing cluster", () => { beforeEach(() => { @@ -229,17 +229,17 @@ describe("pre 2.0 config with an existing cluster", () => { mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); it("migrates to modern format with kubeconfig in a file", async () => { const config = clusterStore.clustersList[0].kubeConfigPath; expect(fs.readFileSync(config, "utf8")).toBe("kubeconfig content"); - }) -}) + }); +}); describe("pre 2.6.0 config with a cluster that has arrays in auth config", () => { beforeEach(() => { @@ -257,15 +257,15 @@ describe("pre 2.6.0 config with a cluster that has arrays in auth config", () => }, }) } - } + }; mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); it("replaces array format access token and expiry into string", async () => { const file = clusterStore.clustersList[0].kubeConfigPath; @@ -273,8 +273,8 @@ describe("pre 2.6.0 config with a cluster that has arrays in auth config", () => 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"); - }) -}) + }); +}); describe("pre 2.6.0 config with a cluster icon", () => { beforeEach(() => { @@ -297,23 +297,23 @@ describe("pre 2.6.0 config with a cluster icon", () => { }), "icon_path": testDataIcon, } - } + }; mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); 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.preferences.icon.startsWith("data:;base64,")).toBe(true); - }) -}) + }); +}); describe("for a pre 2.7.0-beta.0 config without a workspace", () => { beforeEach(() => { @@ -334,21 +334,21 @@ describe("for a pre 2.7.0-beta.0 config without a workspace", () => { }, }) } - } + }; mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); it("adds cluster to default workspace", async () => { const storedClusterData = clusterStore.clustersList[0]; expect(storedClusterData.workspace).toBe('default'); - }) -}) + }); +}); describe("pre 3.6.0-beta.1 config with an existing cluster", () => { beforeEach(() => { @@ -378,19 +378,19 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => { mockFs(mockOpts); clusterStore = ClusterStore.getInstance(); return clusterStore.load(); - }) + }); afterEach(() => { mockFs.restore(); - }) + }); it("migrates to modern format with kubeconfig in a file", async () => { const config = clusterStore.clustersList[0].kubeConfigPath; expect(fs.readFileSync(config, "utf8")).toBe("kubeconfig content"); - }) + }); it("migrates to modern format with icon not in file", async () => { const { icon } = clusterStore.clustersList[0].preferences; expect(icon.startsWith("data:;base64,")).toBe(true); - }) -}) + }); +}); diff --git a/src/common/__tests__/event-bus.test.ts b/src/common/__tests__/event-bus.test.ts index 7daa9ed9b0..cfd82f54a3 100644 --- a/src/common/__tests__/event-bus.test.ts +++ b/src/common/__tests__/event-bus.test.ts @@ -1,15 +1,15 @@ -import { appEventBus, AppEvent } from "../event-bus" +import { appEventBus, AppEvent } from "../event-bus"; describe("event bus tests", () => { describe("emit", () => { it("emits an event", () => { - let event: AppEvent = null + let event: AppEvent = null; appEventBus.addListener((data) => { - event = data - }) + event = data; + }); - appEventBus.emit({name: "foo", action: "bar"}) - expect(event.name).toBe("foo") - }) - }) -}) + appEventBus.emit({name: "foo", action: "bar"}); + expect(event.name).toBe("foo"); + }); + }); +}); diff --git a/src/common/__tests__/search-store.test.ts b/src/common/__tests__/search-store.test.ts index 517182a04a..3f4125d1c0 100644 --- a/src/common/__tests__/search-store.test.ts +++ b/src/common/__tests__/search-store.test.ts @@ -2,7 +2,7 @@ * @jest-environment jsdom */ -import { SearchStore } from "../search-store" +import { SearchStore } from "../search-store"; let searchStore: SearchStore = null; @@ -10,17 +10,17 @@ const logs = [ "1:M 30 Oct 2020 16:17:41.553 # Connection with replica 172.17.0.12:6379 lost", "1:M 30 Oct 2020 16:17:41.623 * Replica 172.17.0.12:6379 asks for synchronization", "1:M 30 Oct 2020 16:17:41.623 * Starting Partial resynchronization request from 172.17.0.12:6379 accepted. Sending 0 bytes of backlog starting from offset 14407." -] +]; describe("search store tests", () => { beforeEach(async () => { searchStore = new SearchStore(); - }) + }); it("does nothing with empty search query", () => { searchStore.onSearch([], ""); expect(searchStore.occurrences).toEqual([]); - }) + }); it("doesn't break if no text provided", () => { searchStore.onSearch(null, "replica"); @@ -28,53 +28,53 @@ describe("search store tests", () => { searchStore.onSearch([], "replica"); expect(searchStore.occurrences).toEqual([]); - }) + }); it("find 3 occurences across 3 lines", () => { searchStore.onSearch(logs, "172"); expect(searchStore.occurrences).toEqual([0, 1, 2]); - }) + }); it("find occurences within 1 line (case-insensitive)", () => { searchStore.onSearch(logs, "Starting"); expect(searchStore.occurrences).toEqual([2, 2]); - }) + }); it("sets overlay index equal to first occurence", () => { searchStore.onSearch(logs, "Replica"); expect(searchStore.activeOverlayIndex).toBe(0); - }) + }); it("set overlay index to next occurence", () => { searchStore.onSearch(logs, "172"); searchStore.setNextOverlayActive(); expect(searchStore.activeOverlayIndex).toBe(1); - }) + }); it("sets overlay to last occurence", () => { searchStore.onSearch(logs, "172"); searchStore.setPrevOverlayActive(); expect(searchStore.activeOverlayIndex).toBe(2); - }) + }); it("gets line index where overlay is located", () => { searchStore.onSearch(logs, "synchronization"); expect(searchStore.activeOverlayLine).toBe(1); - }) + }); it("escapes string for using in regex", () => { const regex = searchStore.escapeRegex("some.interesting-query\\#?()[]"); expect(regex).toBe("some\\.interesting\\-query\\\\\\#\\?\\(\\)\\[\\]"); - }) + }); it("gets active find number", () => { searchStore.onSearch(logs, "172"); searchStore.setNextOverlayActive(); expect(searchStore.activeFind).toBe(2); - }) + }); it("gets total finds number", () => { searchStore.onSearch(logs, "Starting"); expect(searchStore.totalFinds).toBe(2); - }) -}) \ No newline at end of file + }); +}); \ No newline at end of file diff --git a/src/common/__tests__/user-store.test.ts b/src/common/__tests__/user-store.test.ts index 593992415f..05b668873a 100644 --- a/src/common/__tests__/user-store.test.ts +++ b/src/common/__tests__/user-store.test.ts @@ -1,4 +1,4 @@ -import mockFs from "mock-fs" +import mockFs from "mock-fs"; jest.mock("electron", () => { return { @@ -7,55 +7,55 @@ jest.mock("electron", () => { getPath: () => 'tmp', getLocale: () => 'en' } - } -}) + }; +}); -import { UserStore } from "../user-store" -import { SemVer } from "semver" -import electron from "electron" +import { UserStore } from "../user-store"; +import { SemVer } from "semver"; +import electron from "electron"; describe("user store tests", () => { describe("for an empty config", () => { beforeEach(() => { - UserStore.resetInstance() - mockFs({ tmp: { 'config.json': "{}" } }) - }) + UserStore.resetInstance(); + mockFs({ tmp: { 'config.json': "{}" } }); + }); afterEach(() => { - mockFs.restore() - }) + mockFs.restore(); + }); it("allows setting and retrieving lastSeenAppVersion", () => { const us = UserStore.getInstance(); us.lastSeenAppVersion = "1.2.3"; expect(us.lastSeenAppVersion).toBe("1.2.3"); - }) + }); it("allows adding and listing seen contexts", () => { const us = UserStore.getInstance(); - us.seenContexts.add('foo') - expect(us.seenContexts.size).toBe(1) + us.seenContexts.add('foo'); + expect(us.seenContexts.size).toBe(1); - 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) - }) + 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); + }); it("allows setting and getting preferences", () => { const us = UserStore.getInstance(); us.preferences.httpsProxy = 'abcd://defg'; - expect(us.preferences.httpsProxy).toBe('abcd://defg') - expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme) + 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 () => { const us = UserStore.getInstance(); @@ -64,7 +64,7 @@ describe("user store tests", () => { us.preferences.colorTheme = "some other theme"; await us.resetTheme(); expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme); - }) + }); it("correctly calculates if the last seen version is an old release", () => { const us = UserStore.getInstance(); @@ -73,12 +73,12 @@ describe("user store tests", () => { us.lastSeenAppVersion = (new SemVer(electron.app.getVersion())).inc("major").format(); expect(us.isNewVersion).toBe(false); - }) - }) + }); + }); describe("migrations", () => { beforeEach(() => { - UserStore.resetInstance() + UserStore.resetInstance(); mockFs({ 'tmp': { 'config.json': JSON.stringify({ @@ -87,17 +87,17 @@ describe("user store tests", () => { lastSeenAppVersion: '1.2.3' }) } - }) - }) + }); + }); afterEach(() => { - mockFs.restore() - }) + mockFs.restore(); + }); it("sets last seen app version to 0.0.0", () => { const us = UserStore.getInstance(); - expect(us.lastSeenAppVersion).toBe('0.0.0') - }) - }) -}) \ No newline at end of file + expect(us.lastSeenAppVersion).toBe('0.0.0'); + }); + }); +}); \ No newline at end of file diff --git a/src/common/__tests__/workspace-store.test.ts b/src/common/__tests__/workspace-store.test.ts index ef492bfcfa..86c76db6ca 100644 --- a/src/common/__tests__/workspace-store.test.ts +++ b/src/common/__tests__/workspace-store.test.ts @@ -1,4 +1,4 @@ -import mockFs from "mock-fs" +import mockFs from "mock-fs"; jest.mock("electron", () => { return { @@ -7,36 +7,36 @@ jest.mock("electron", () => { getPath: () => 'tmp', getLocale: () => 'en' } - } -}) + }; +}); -import { Workspace, WorkspaceStore } from "../workspace-store" +import { Workspace, WorkspaceStore } from "../workspace-store"; describe("workspace store tests", () => { describe("for an empty config", () => { beforeEach(async () => { - WorkspaceStore.resetInstance() - mockFs({ tmp: { 'lens-workspace-store.json': "{}" } }) + WorkspaceStore.resetInstance(); + mockFs({ tmp: { 'lens-workspace-store.json': "{}" } }); await WorkspaceStore.getInstance().load(); - }) + }); afterEach(() => { - mockFs.restore() - }) + mockFs.restore(); + }); it("default workspace should always exist", () => { const ws = WorkspaceStore.getInstance(); expect(ws.workspaces.size).toBe(1); expect(ws.getById(WorkspaceStore.defaultId)).not.toBe(null); - }) + }); it("cannot remove the default workspace", () => { const ws = WorkspaceStore.getInstance(); expect(() => ws.removeWorkspaceById(WorkspaceStore.defaultId)).toThrowError("Cannot remove"); - }) + }); it("can update workspace description", () => { const ws = WorkspaceStore.getInstance(); @@ -50,7 +50,7 @@ describe("workspace store tests", () => { ws.updateWorkspace(workspace); expect(ws.getById("foobar").description).toBe("Foobar description"); - }) + }); it("can add workspaces", () => { const ws = WorkspaceStore.getInstance(); @@ -61,13 +61,13 @@ describe("workspace store tests", () => { })); expect(ws.getById("123").name).toBe("foobar"); - }) + }); it("cannot set a non-existent workspace to be active", () => { const ws = WorkspaceStore.getInstance(); expect(() => ws.setActive("abc")).toThrow("doesn't exist"); - }) + }); it("can set a existent workspace to be active", () => { const ws = WorkspaceStore.getInstance(); @@ -78,7 +78,7 @@ describe("workspace store tests", () => { })); expect(() => ws.setActive("abc")).not.toThrowError(); - }) + }); it("can remove a workspace", () => { const ws = WorkspaceStore.getInstance(); @@ -94,7 +94,7 @@ describe("workspace store tests", () => { ws.removeWorkspaceById("123"); expect(ws.workspaces.size).toBe(2); - }) + }); it("cannot create workspace with existent name", () => { const ws = WorkspaceStore.getInstance(); @@ -105,7 +105,7 @@ describe("workspace store tests", () => { })); expect(ws.workspacesList.length).toBe(1); // default workspace only - }) + }); it("cannot create workspace with empty name", () => { const ws = WorkspaceStore.getInstance(); @@ -116,7 +116,7 @@ describe("workspace store tests", () => { })); expect(ws.workspacesList.length).toBe(1); // default workspace only - }) + }); it("cannot create workspace with ' ' name", () => { const ws = WorkspaceStore.getInstance(); @@ -127,7 +127,7 @@ describe("workspace store tests", () => { })); expect(ws.workspacesList.length).toBe(1); // default workspace only - }) + }); it("trim workspace name", () => { const ws = WorkspaceStore.getInstance(); @@ -138,12 +138,12 @@ describe("workspace store tests", () => { })); expect(ws.workspacesList.length).toBe(1); // default workspace only - }) - }) + }); + }); describe("for a non-empty config", () => { beforeEach(async () => { - WorkspaceStore.resetInstance() + WorkspaceStore.resetInstance(); mockFs({ tmp: { 'lens-workspace-store.json': JSON.stringify({ @@ -157,19 +157,19 @@ describe("workspace store tests", () => { }] }) } - }) + }); await WorkspaceStore.getInstance().load(); - }) + }); afterEach(() => { - mockFs.restore() - }) + mockFs.restore(); + }); it("doesn't revert to default workspace", async () => { const ws = WorkspaceStore.getInstance(); expect(ws.currentWorkspaceId).toBe("abc"); - }) - }) -}) + }); + }); +}); diff --git a/src/common/base-store.ts b/src/common/base-store.ts index e9df396810..8b5fc98c32 100644 --- a/src/common/base-store.ts +++ b/src/common/base-store.ts @@ -1,7 +1,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 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 Singleton from "./utils/singleton"; import { getAppVersion } from "./utils/app-version"; @@ -32,7 +32,7 @@ export abstract class BaseStore extends Singleton { autoLoad: false, syncEnabled: true, ...params, - } + }; this.init(); } @@ -41,11 +41,11 @@ export abstract class BaseStore extends Singleton { } protected get syncRendererChannel() { - return `store-sync-renderer:${this.path}` + return `store-sync-renderer:${this.path}`; } protected get syncMainChannel() { - return `store-sync-main:${this.path}` + return `store-sync-main:${this.path}`; } get path() { @@ -76,7 +76,7 @@ export abstract class BaseStore extends Singleton { } protected cwd() { - return (app || remote.app).getPath("userData") + return (app || remote.app).getPath("userData"); } protected async saveToFile(model: T) { @@ -96,7 +96,7 @@ export abstract class BaseStore extends Singleton { logger.silly(`[STORE]: SYNC ${this.name} from renderer`, { model }); this.onSync(model); }; - subscribeToBroadcast(this.syncMainChannel, callback) + subscribeToBroadcast(this.syncMainChannel, callback); this.syncDisposers.push(() => unsubscribeFromBroadcast(this.syncMainChannel, callback)); } if (ipcRenderer) { @@ -104,20 +104,20 @@ export abstract class BaseStore extends Singleton { logger.silly(`[STORE]: SYNC ${this.name} from main`, { model }); this.onSyncFromMain(model); }; - subscribeToBroadcast(this.syncRendererChannel, callback) + subscribeToBroadcast(this.syncRendererChannel, callback); this.syncDisposers.push(() => unsubscribeFromBroadcast(this.syncRendererChannel, callback)); } } protected onSyncFromMain(model: T) { this.applyWithoutSync(() => { - this.onSync(model) - }) + this.onSync(model); + }); } unregisterIpcListener() { - ipcRenderer.removeAllListeners(this.syncMainChannel) - ipcRenderer.removeAllListeners(this.syncRendererChannel) + ipcRenderer.removeAllListeners(this.syncMainChannel); + ipcRenderer.removeAllListeners(this.syncRendererChannel); } disableSync() { @@ -143,9 +143,9 @@ export abstract class BaseStore extends Singleton { protected async onModelChange(model: T) { if (ipcMain) { this.saveToFile(model); // save config file - broadcastMessage(this.syncRendererChannel, model) + broadcastMessage(this.syncRendererChannel, model); } else { - broadcastMessage(this.syncMainChannel, model) + broadcastMessage(this.syncMainChannel, model); } } diff --git a/src/common/cluster-frames.ts b/src/common/cluster-frames.ts index af950b0785..cf82bc4646 100644 --- a/src/common/cluster-frames.ts +++ b/src/common/cluster-frames.ts @@ -1,3 +1,3 @@ -import { observable } from "mobx" +import { observable } from "mobx"; export const clusterFrameMap = observable.map(); diff --git a/src/common/cluster-ipc.ts b/src/common/cluster-ipc.ts index c2204bc6b4..18c0ea0a12 100644 --- a/src/common/cluster-ipc.ts +++ b/src/common/cluster-ipc.ts @@ -1,15 +1,15 @@ import { handleRequest } from "./ipc"; import { ClusterId, clusterStore } from "./cluster-store"; -import { appEventBus } from "./event-bus" +import { appEventBus } from "./event-bus"; import { ResourceApplier } from "../main/resource-applier"; import { ipcMain } from "electron"; -import { clusterFrameMap } from "./cluster-frames" +import { clusterFrameMap } from "./cluster-frames"; -export const clusterActivateHandler = "cluster:activate" -export const clusterSetFrameIdHandler = "cluster:set-frame-id" -export const clusterRefreshHandler = "cluster:refresh" -export const clusterDisconnectHandler = "cluster:disconnect" -export const clusterKubectlApplyAllHandler = "cluster:kubectl-apply-all" +export const clusterActivateHandler = "cluster:activate"; +export const clusterSetFrameIdHandler = "cluster:set-frame-id"; +export const clusterRefreshHandler = "cluster:refresh"; +export const clusterDisconnectHandler = "cluster:disconnect"; +export const clusterKubectlApplyAllHandler = "cluster:kubectl-apply-all"; if (ipcMain) { @@ -18,38 +18,38 @@ if (ipcMain) { if (cluster) { return cluster.activate(force); } - }) + }); handleRequest(clusterSetFrameIdHandler, (event, clusterId: ClusterId, frameId: number) => { const cluster = clusterStore.getById(clusterId); if (cluster) { - clusterFrameMap.set(cluster.id, frameId) + clusterFrameMap.set(cluster.id, frameId); return cluster.pushState(); } - }) + }); handleRequest(clusterRefreshHandler, (event, clusterId: ClusterId) => { const cluster = clusterStore.getById(clusterId); - if (cluster) return cluster.refresh({ refreshMetadata: true }) - }) + if (cluster) return cluster.refresh({ refreshMetadata: true }); + }); handleRequest(clusterDisconnectHandler, (event, clusterId: ClusterId) => { appEventBus.emit({name: "cluster", action: "stop"}); const cluster = clusterStore.getById(clusterId); if (cluster) { cluster.disconnect(); - clusterFrameMap.delete(cluster.id) + clusterFrameMap.delete(cluster.id); } - }) + }); handleRequest(clusterKubectlApplyAllHandler, (event, clusterId: ClusterId, resources: string[]) => { - appEventBus.emit({name: "cluster", action: "kubectl-apply-all"}) + appEventBus.emit({name: "cluster", action: "kubectl-apply-all"}); const cluster = clusterStore.getById(clusterId); if (cluster) { - const applier = new ResourceApplier(cluster) - applier.kubectlApplyAll(resources) + const applier = new ResourceApplier(cluster); + applier.kubectlApplyAll(resources); } else { throw `${clusterId} is not a valid cluster id`; } - }) + }); } diff --git a/src/common/cluster-store.ts b/src/common/cluster-store.ts index da99ce439f..24c89d7ca9 100644 --- a/src/common/cluster-store.ts +++ b/src/common/cluster-store.ts @@ -5,9 +5,9 @@ import { unlink } from "fs-extra"; import { action, computed, observable, reaction, toJS } from "mobx"; import { BaseStore } from "./base-store"; import { Cluster, ClusterState } from "../main/cluster"; -import migrations from "../migrations/cluster-store" +import migrations from "../migrations/cluster-store"; import logger from "../main/logger"; -import { appEventBus } from "./event-bus" +import { appEventBus } from "./event-bus"; import { dumpConfigYaml } from "./kube-helpers"; import { saveToAppFiles } from "./utils/saveToAppFiles"; import { KubeConfig } from "@kubernetes/client-node"; @@ -86,38 +86,38 @@ export class ClusterStore extends BaseStore { migrations: migrations, }); - this.pushStateToViewsAutomatically() + this.pushStateToViewsAutomatically(); } protected pushStateToViewsAutomatically() { if (!ipcRenderer) { reaction(() => this.connectedClustersList, () => { - this.pushState() - }) + this.pushState(); + }); } } registerIpcListener() { - logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`) + logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`); subscribeToBroadcast("cluster:state", (event, clusterId: string, state: ClusterState) => { logger.silly(`[CLUSTER-STORE]: received push-state at ${location.host} (${webFrame.routingId})`, clusterId, state); - this.getById(clusterId)?.setState(state) - }) + this.getById(clusterId)?.setState(state); + }); } unregisterIpcListener() { - super.unregisterIpcListener() - unsubscribeAllFromBroadcast("cluster:state") + super.unregisterIpcListener(); + unsubscribeAllFromBroadcast("cluster:state"); } pushState() { this.clusters.forEach((c) => { - c.pushState() - }) + c.pushState(); + }); } get activeClusterId() { - return this.activeCluster + return this.activeCluster; } @computed get clustersList(): Cluster[] { @@ -125,7 +125,7 @@ export class ClusterStore extends BaseStore { } @computed get enabledClustersList(): Cluster[] { - return this.clustersList.filter((c) => c.enabled) + return this.clustersList.filter((c) => c.enabled); } @computed get active(): Cluster | null { @@ -133,7 +133,7 @@ export class ClusterStore extends BaseStore { } @computed get connectedClustersList(): Cluster[] { - return this.clustersList.filter((c) => !c.disconnected) + return this.clustersList.filter((c) => !c.disconnected); } isActive(id: ClusterId) { @@ -149,7 +149,7 @@ export class ClusterStore extends BaseStore { swapIconOrders(workspace: WorkspaceId, from: number, to: number) { const clusters = this.getByWorkspaceId(workspace); if (from < 0 || to < 0 || from >= clusters.length || to >= clusters.length || isNaN(from) || isNaN(to)) { - throw new Error(`invalid from<->to arguments`) + throw new Error(`invalid from<->to arguments`); } move.mutate(clusters, from, to); @@ -170,37 +170,37 @@ export class ClusterStore extends BaseStore { getByWorkspaceId(workspaceId: string): Cluster[] { const clusters = Array.from(this.clusters.values()) .filter(cluster => cluster.workspace === workspaceId); - return _.sortBy(clusters, cluster => cluster.preferences.iconOrder) + return _.sortBy(clusters, cluster => cluster.preferences.iconOrder); } @action addClusters(...models: ClusterModel[]): Cluster[] { - const clusters: Cluster[] = [] + const clusters: Cluster[] = []; models.forEach(model => { - clusters.push(this.addCluster(model)) - }) + clusters.push(this.addCluster(model)); + }); - return clusters + return clusters; } @action addCluster(model: ClusterModel | Cluster): Cluster { - appEventBus.emit({ name: "cluster", action: "add" }) + appEventBus.emit({ name: "cluster", action: "add" }); let cluster = model as Cluster; if (!(model instanceof Cluster)) { - cluster = new Cluster(model) + cluster = new Cluster(model); } this.clusters.set(model.id, cluster); - return cluster + return cluster; } async removeCluster(model: ClusterModel) { - await this.removeById(model.id) + await this.removeById(model.id); } @action async removeById(clusterId: ClusterId) { - appEventBus.emit({ name: "cluster", action: "remove" }) + appEventBus.emit({ name: "cluster", action: "remove" }); const cluster = this.getById(clusterId); if (cluster) { this.clusters.delete(clusterId); @@ -217,8 +217,8 @@ export class ClusterStore extends BaseStore { @action removeByWorkspaceId(workspaceId: string) { this.getByWorkspaceId(workspaceId).forEach(cluster => { - this.removeById(cluster.id) - }) + this.removeById(cluster.id); + }); } @action @@ -235,7 +235,7 @@ export class ClusterStore extends BaseStore { } else { cluster = new Cluster(clusterModel); if (!cluster.isManaged) { - cluster.enabled = true + cluster.enabled = true; } } newClusters.set(clusterModel.id, cluster); @@ -259,7 +259,7 @@ export class ClusterStore extends BaseStore { clusters: this.clustersList.map(cluster => cluster.toJSON()), }, { recurseEverything: true - }) + }); } } diff --git a/src/common/event-bus.ts b/src/common/event-bus.ts index 4259467380..a05a43bcd1 100644 --- a/src/common/event-bus.ts +++ b/src/common/event-bus.ts @@ -1,9 +1,9 @@ -import { EventEmitter } from "./event-emitter" +import { EventEmitter } from "./event-emitter"; export type AppEvent = { name: string; action: string; params?: object; -} +}; -export const appEventBus = new EventEmitter<[AppEvent]>() +export const appEventBus = new EventEmitter<[AppEvent]>(); diff --git a/src/common/event-emitter.ts b/src/common/event-emitter.ts index f3a2a48bfb..d018dce337 100644 --- a/src/common/event-emitter.ts +++ b/src/common/event-emitter.ts @@ -35,6 +35,6 @@ export class EventEmitter { const result = callback(...data); if (result === false) return; // break cycle return true; - }) + }); } } diff --git a/src/common/ipc.ts b/src/common/ipc.ts index 882498a3a4..2ff513c357 100644 --- a/src/common/ipc.ts +++ b/src/common/ipc.ts @@ -7,24 +7,24 @@ import logger from "../main/logger"; import { clusterFrameMap } from "./cluster-frames"; export function handleRequest(channel: string, listener: (...args: any[]) => any) { - ipcMain.handle(channel, listener) + ipcMain.handle(channel, listener); } export async function requestMain(channel: string, ...args: any[]) { - return ipcRenderer.invoke(channel, ...args) + return ipcRenderer.invoke(channel, ...args); } async function getSubFrames(): Promise { const subFrames: number[] = []; clusterFrameMap.forEach((frameId, _) => { - subFrames.push(frameId) + subFrames.push(frameId); }); return subFrames; } export function broadcastMessage(channel: string, ...args: any[]) { const views = (webContents || remote?.webContents)?.getAllWebContents(); - if (!views) return + if (!views) return; views.forEach(webContent => { const type = webContent.getType(); @@ -32,39 +32,39 @@ export function broadcastMessage(channel: string, ...args: any[]) { webContent.send(channel, ...args); getSubFrames().then((frames) => { frames.map((frameId) => { - webContent.sendToFrame(frameId, channel, ...args) - }) - }).catch((e) => e) - }) + webContent.sendToFrame(frameId, channel, ...args); + }); + }).catch((e) => e); + }); if (ipcRenderer) { - ipcRenderer.send(channel, ...args) + ipcRenderer.send(channel, ...args); } else { - ipcMain.emit(channel, ...args) + ipcMain.emit(channel, ...args); } } export function subscribeToBroadcast(channel: string, listener: (...args: any[]) => any) { if (ipcRenderer) { - ipcRenderer.on(channel, listener) + ipcRenderer.on(channel, listener); } else { - ipcMain.on(channel, listener) + ipcMain.on(channel, listener); } - return listener + return listener; } export function unsubscribeFromBroadcast(channel: string, listener: (...args: any[]) => any) { if (ipcRenderer) { - ipcRenderer.off(channel, listener) + ipcRenderer.off(channel, listener); } else { - ipcMain.off(channel, listener) + ipcMain.off(channel, listener); } } export function unsubscribeAllFromBroadcast(channel: string) { if (ipcRenderer) { - ipcRenderer.removeAllListeners(channel) + ipcRenderer.removeAllListeners(channel); } else { - ipcMain.removeAllListeners(channel) + ipcMain.removeAllListeners(channel); } } diff --git a/src/common/kube-helpers.ts b/src/common/kube-helpers.ts index 8f517ba555..ecb85f78b9 100644 --- a/src/common/kube-helpers.ts +++ b/src/common/kube-helpers.ts @@ -1,8 +1,8 @@ -import { KubeConfig, V1Node, V1Pod } from "@kubernetes/client-node" +import { KubeConfig, V1Node, V1Pod } from "@kubernetes/client-node"; import fse from "fs-extra"; -import path from "path" -import os from "os" -import yaml from "js-yaml" +import path from "path"; +import os from "os"; +import yaml from "js-yaml"; import logger from "../main/logger"; import commandExists from "command-exists"; import { ExecValidationNotFoundError } from "./custom-errors"; @@ -25,7 +25,7 @@ export function loadConfig(pathOrContent?: string): KubeConfig { kc.loadFromString(pathOrContent); } - return kc + return kc; } /** @@ -39,33 +39,33 @@ export function validateConfig(config: KubeConfig | string): KubeConfig { if (typeof config == "string") { config = loadConfig(config); } - logger.debug(`validating kube config: ${JSON.stringify(config)}`) + logger.debug(`validating kube config: ${JSON.stringify(config)}`); if (!config.users || config.users.length == 0) { - throw new Error("No users provided in config") + throw new Error("No users provided in config"); } if (!config.clusters || config.clusters.length == 0) { - throw new Error("No clusters provided in config") + throw new Error("No clusters provided in config"); } if (!config.contexts || config.contexts.length == 0) { - throw new Error("No contexts provided in config") + throw new Error("No contexts provided in config"); } - return config + return config; } /** * Breaks kube config into several configs. Each context as it own KubeConfig object */ export function splitConfig(kubeConfig: KubeConfig): KubeConfig[] { - const configs: KubeConfig[] = [] + const configs: KubeConfig[] = []; if (!kubeConfig.contexts) { return configs; } kubeConfig.contexts.forEach(ctx => { const kc = new KubeConfig(); kc.clusters = [kubeConfig.getCluster(ctx.cluster)].filter(n => n); - kc.users = [kubeConfig.getUser(ctx.user)].filter(n => n) - kc.contexts = [kubeConfig.getContextObject(ctx.name)].filter(n => n) + kc.users = [kubeConfig.getUser(ctx.user)].filter(n => n); + kc.contexts = [kubeConfig.getContextObject(ctx.name)].filter(n => n); kc.setCurrentContext(ctx.name); configs.push(kc); @@ -88,7 +88,7 @@ export function dumpConfigYaml(kubeConfig: Partial): string { server: cluster.server, 'insecure-skip-tls-verify': cluster.skipTLSVerify } - } + }; }), contexts: kubeConfig.contexts.map(context => { return { @@ -98,7 +98,7 @@ export function dumpConfigYaml(kubeConfig: Partial): string { user: context.user, namespace: context.namespace } - } + }; }), users: kubeConfig.users.map(user => { return { @@ -114,9 +114,9 @@ export function dumpConfigYaml(kubeConfig: Partial): string { username: user.username, password: user.password } - } + }; }) - } + }; logger.debug("Dumping KubeConfig:", config); @@ -127,20 +127,20 @@ export function dumpConfigYaml(kubeConfig: Partial): string { export function podHasIssues(pod: V1Pod) { // Logic adapted from dashboard const notReady = !!pod.status.conditions.find(condition => { - return condition.type == "Ready" && condition.status !== "True" + return condition.type == "Ready" && condition.status !== "True"; }); return ( notReady || pod.status.phase !== "Running" || pod.spec.priority > 500000 // We're interested in high prio pods events regardless of their running status - ) + ); } export function getNodeWarningConditions(node: V1Node) { return node.status.conditions.filter(c => c.status.toLowerCase() === "true" && c.type !== "Ready" && c.type !== "HostUpgrades" - ) + ); } /** diff --git a/src/common/prometheus-providers.ts b/src/common/prometheus-providers.ts index 2c6e6fac8e..6f6b379ec7 100644 --- a/src/common/prometheus-providers.ts +++ b/src/common/prometheus-providers.ts @@ -5,8 +5,8 @@ import { PrometheusStacklight } from "../main/prometheus/stacklight"; import { PrometheusProviderRegistry } from "../main/prometheus/provider-registry"; [PrometheusLens, PrometheusHelm, PrometheusOperator, PrometheusStacklight].forEach(providerClass => { - const provider = new providerClass() - PrometheusProviderRegistry.registerProvider(provider.id, provider) + const provider = new providerClass(); + PrometheusProviderRegistry.registerProvider(provider.id, provider); }); -export const prometheusProviders = PrometheusProviderRegistry.getProviders() \ No newline at end of file +export const prometheusProviders = PrometheusProviderRegistry.getProviders(); \ No newline at end of file diff --git a/src/common/rbac.ts b/src/common/rbac.ts index 363a94f3e2..4097de95c9 100644 --- a/src/common/rbac.ts +++ b/src/common/rbac.ts @@ -4,7 +4,7 @@ export type KubeResource = "namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumes" | "storageclasses" | "pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" | - "endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" + "endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets"; export interface KubeApiResource { resource: KubeResource; // valid resource name diff --git a/src/common/register-protocol.ts b/src/common/register-protocol.ts index ff9d310f57..fd5ed61daa 100644 --- a/src/common/register-protocol.ts +++ b/src/common/register-protocol.ts @@ -1,6 +1,6 @@ // Register custom protocols -import { protocol } from "electron" +import { protocol } from "electron"; import path from "path"; export function registerFileProtocol(name: string, basePath: string) { @@ -8,5 +8,5 @@ export function registerFileProtocol(name: string, basePath: string) { const filePath = request.url.replace(name + "://", ""); const absPath = path.resolve(basePath, filePath); callback({ path: absPath }); - }) + }); } diff --git a/src/common/request.ts b/src/common/request.ts index 536e2eccc9..1ebec8c33f 100644 --- a/src/common/request.ts +++ b/src/common/request.ts @@ -1,28 +1,28 @@ -import request from "request" -import requestPromise from "request-promise-native" -import { userStore } from "./user-store" +import request from "request"; +import requestPromise from "request-promise-native"; +import { userStore } from "./user-store"; // todo: get rid of "request" (deprecated) // https://github.com/lensapp/lens/issues/459 function getDefaultRequestOpts(): Partial { - const { httpsProxy, allowUntrustedCAs } = userStore.preferences + const { httpsProxy, allowUntrustedCAs } = userStore.preferences; return { proxy: httpsProxy || undefined, rejectUnauthorized: !allowUntrustedCAs, - } + }; } /** * @deprecated */ export function customRequest(opts: request.Options) { - return request.defaults(getDefaultRequestOpts())(opts) + return request.defaults(getDefaultRequestOpts())(opts); } /** * @deprecated */ export function customRequestPromise(opts: requestPromise.Options) { - return requestPromise.defaults(getDefaultRequestOpts())(opts) + return requestPromise.defaults(getDefaultRequestOpts())(opts); } diff --git a/src/common/system-ca.ts b/src/common/system-ca.ts index 957f374785..005ca78884 100644 --- a/src/common/system-ca.ts +++ b/src/common/system-ca.ts @@ -1,14 +1,14 @@ import { isMac, isWindows } from "./vars"; -import winca from "win-ca" -import macca from "mac-ca" -import logger from "../main/logger" +import winca from "win-ca"; +import macca from "mac-ca"; +import logger from "../main/logger"; if (isMac) { for (const crt of macca.all()) { - const attributes = crt.issuer?.attributes?.map((a: any) => `${a.name}=${a.value}`) - logger.debug("Using host CA: " + attributes.join(",")) + const attributes = crt.issuer?.attributes?.map((a: any) => `${a.name}=${a.value}`); + logger.debug("Using host CA: " + attributes.join(",")); } } if (isWindows) { - winca.inject("+") // see: https://github.com/ukoloff/win-ca#caveats + winca.inject("+"); // see: https://github.com/ukoloff/win-ca#caveats } diff --git a/src/common/user-store.ts b/src/common/user-store.ts index 6a988d4004..c1eba70a43 100644 --- a/src/common/user-store.ts +++ b/src/common/user-store.ts @@ -1,13 +1,13 @@ import type { ThemeId } from "../renderer/theme.store"; import { app, remote } from 'electron'; -import semver from "semver" -import { readFile } from "fs-extra" +import semver from "semver"; +import { readFile } from "fs-extra"; import { action, observable, reaction, toJS } from "mobx"; import { BaseStore } from "./base-store"; -import migrations from "../migrations/user-store" +import migrations from "../migrations/user-store"; import { getAppVersion } from "./utils/app-version"; import { kubeConfigDefaultPath, loadConfig } from "./kube-helpers"; -import { appEventBus } from "./event-bus" +import { appEventBus } from "./event-bus"; import logger from "../main/logger"; import path from 'path'; @@ -31,7 +31,7 @@ export interface UserPreferences { } export class UserStore extends BaseStore { - static readonly defaultTheme: ThemeId = "lens-dark" + static readonly defaultTheme: ThemeId = "lens-dark"; private constructor() { super({ @@ -42,7 +42,7 @@ export class UserStore extends BaseStore { this.handleOnLoad(); } - @observable lastSeenAppVersion = "0.0.0" + @observable lastSeenAppVersion = "0.0.0"; @observable kubeConfigPath = kubeConfigDefaultPath; // used in add-cluster page for providing context @observable seenContexts = observable.set(); @observable newContexts = observable.set(); @@ -66,7 +66,7 @@ export class UserStore extends BaseStore { if (app) { // track telemetry availability reaction(() => this.preferences.allowTelemetry, allowed => { - appEventBus.emit({name: "telemetry", action: allowed ? "enabled" : "disabled"}) + appEventBus.emit({name: "telemetry", action: allowed ? "enabled" : "disabled"}); }); // open at system start-up @@ -95,7 +95,7 @@ export class UserStore extends BaseStore { @action saveLastSeenAppVersion() { - appEventBus.emit({name: "app", action: "whats-new-seen"}) + appEventBus.emit({name: "app", action: "whats-new-seen"}); this.lastSeenAppVersion = getAppVersion(); } @@ -113,7 +113,7 @@ export class UserStore extends BaseStore { logger.error(err); this.resetKubeConfigPath(); } - } + }; @action markNewContextsAsSeen() { @@ -127,12 +127,12 @@ export class UserStore extends BaseStore { * @returns string */ getDefaultKubectlPath(): string { - return path.join((app || remote.app).getPath("userData"), "binaries") + return path.join((app || remote.app).getPath("userData"), "binaries"); } @action protected async fromStore(data: Partial = {}) { - const { lastSeenAppVersion, seenContexts = [], preferences, kubeConfigPath } = data + const { lastSeenAppVersion, seenContexts = [], preferences, kubeConfigPath } = data; if (lastSeenAppVersion) { this.lastSeenAppVersion = lastSeenAppVersion; } @@ -149,10 +149,10 @@ export class UserStore extends BaseStore { lastSeenAppVersion: this.lastSeenAppVersion, seenContexts: Array.from(this.seenContexts), preferences: this.preferences, - } + }; return toJS(model, { recurseEverything: true, - }) + }); } } diff --git a/src/common/utils/app-version.ts b/src/common/utils/app-version.ts index e66935ade6..a45f5a55bb 100644 --- a/src/common/utils/app-version.ts +++ b/src/common/utils/app-version.ts @@ -1,4 +1,4 @@ -import packageInfo from "../../../package.json" +import packageInfo from "../../../package.json"; export function getAppVersion(): string { return packageInfo.version; @@ -9,5 +9,5 @@ export function getBundledKubectlVersion(): string { } export function getBundledExtensions(): string[] { - return packageInfo.lens?.extensions || [] + return packageInfo.lens?.extensions || []; } diff --git a/src/common/utils/autobind.ts b/src/common/utils/autobind.ts index ddc76b1db2..8daca1ab85 100644 --- a/src/common/utils/autobind.ts +++ b/src/common/utils/autobind.ts @@ -6,7 +6,7 @@ export function autobind() { return function (target: Constructor | object, prop?: string, descriptor?: PropertyDescriptor) { if (target instanceof Function) return bindClass(target); else return bindMethod(target, prop, descriptor); - } + }; } function bindClass(constructor: T) { @@ -22,12 +22,12 @@ function bindClass(constructor: T) { if (skipMethod(prop)) return; const boundDescriptor = bindMethod(proto, prop, descriptors[prop]); Object.defineProperty(proto, prop, boundDescriptor); - }) + }); } function bindMethod(target: object, prop?: string, descriptor?: PropertyDescriptor) { if (!descriptor || typeof descriptor.value !== "function") { - throw new Error(`@autobind() must be used on class or method only`) + throw new Error(`@autobind() must be used on class or method only`); } const { value: func, enumerable, configurable } = descriptor; const boundFunc = new WeakMap(); diff --git a/src/common/utils/buildUrl.ts b/src/common/utils/buildUrl.ts index cdaf36720c..c26e054491 100644 --- a/src/common/utils/buildUrl.ts +++ b/src/common/utils/buildUrl.ts @@ -1,4 +1,4 @@ -import { compile } from "path-to-regexp" +import { compile } from "path-to-regexp"; export interface IURLParams

{ params?: P; @@ -8,7 +8,7 @@ export interface IURLParams

{ export function buildURL

(path: string | any) { const pathBuilder = compile(String(path)); return function ({ params, query }: IURLParams = {}) { - const queryParams = query ? new URLSearchParams(Object.entries(query)).toString() : "" - return pathBuilder(params) + (queryParams ? `?${queryParams}` : "") - } + const queryParams = query ? new URLSearchParams(Object.entries(query)).toString() : ""; + return pathBuilder(params) + (queryParams ? `?${queryParams}` : ""); + }; } diff --git a/src/common/utils/defineGlobal.ts b/src/common/utils/defineGlobal.ts index 29e2e60ea0..1a4c5993d9 100755 --- a/src/common/utils/defineGlobal.ts +++ b/src/common/utils/defineGlobal.ts @@ -5,7 +5,7 @@ export function defineGlobal(propName: string, descriptor: PropertyDescriptor) { const scope = typeof global !== "undefined" ? global : window; if (scope.hasOwnProperty(propName)) { - console.info(`Global variable "${propName}" already exists. Skipping.`) + console.info(`Global variable "${propName}" already exists. Skipping.`); return; } Object.defineProperty(scope, propName, descriptor); diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 0dfad2d15f..e43863284d 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -1,14 +1,14 @@ // Common utils (main OR renderer) -export * from "./app-version" -export * from "./autobind" -export * from "./base64" -export * from "./camelCase" -export * from "./cloneJson" -export * from "./debouncePromise" -export * from "./defineGlobal" -export * from "./getRandId" -export * from "./splitArray" -export * from "./saveToAppFiles" -export * from "./singleton" -export * from "./openExternal" +export * from "./app-version"; +export * from "./autobind"; +export * from "./base64"; +export * from "./camelCase"; +export * from "./cloneJson"; +export * from "./debouncePromise"; +export * from "./defineGlobal"; +export * from "./getRandId"; +export * from "./splitArray"; +export * from "./saveToAppFiles"; +export * from "./singleton"; +export * from "./openExternal"; diff --git a/src/common/utils/openExternal.ts b/src/common/utils/openExternal.ts index 02c4da6c3b..56d7f90ce6 100644 --- a/src/common/utils/openExternal.ts +++ b/src/common/utils/openExternal.ts @@ -1,5 +1,5 @@ // Opens a link in external browser -import { shell } from "electron" +import { shell } from "electron"; export function openExternal(url: string) { return shell.openExternal(url); diff --git a/src/common/utils/saveToAppFiles.ts b/src/common/utils/saveToAppFiles.ts index e6fab1cfa9..57c47f0d70 100644 --- a/src/common/utils/saveToAppFiles.ts +++ b/src/common/utils/saveToAppFiles.ts @@ -2,7 +2,7 @@ import path from "path"; import { app, remote } from "electron"; import { ensureDirSync, writeFileSync } from "fs-extra"; -import { WriteFileOptions } from "fs" +import { WriteFileOptions } from "fs"; export function saveToAppFiles(filePath: string, contents: any, options?: WriteFileOptions): string { const absPath = path.resolve((app || remote.app).getPath("userData"), filePath); diff --git a/src/common/utils/singleton.ts b/src/common/utils/singleton.ts index 70347f9b42..ed3f0cc962 100644 --- a/src/common/utils/singleton.ts +++ b/src/common/utils/singleton.ts @@ -24,5 +24,5 @@ class Singleton { } } -export { Singleton } +export { Singleton }; export default Singleton; \ No newline at end of file diff --git a/src/common/utils/splitArray.ts b/src/common/utils/splitArray.ts index 90c342827d..f93392f736 100644 --- a/src/common/utils/splitArray.ts +++ b/src/common/utils/splitArray.ts @@ -15,5 +15,5 @@ export function splitArray(array: T[], element: T): [T[], T[], boolean] { if (index < 0) { return [array, [], false]; } - return [array.slice(0, index), array.slice(index + 1, array.length), true] + return [array.slice(0, index), array.slice(index + 1, array.length), true]; } diff --git a/src/common/vars.ts b/src/common/vars.ts index dd792e3bed..1957a6dcff 100644 --- a/src/common/vars.ts +++ b/src/common/vars.ts @@ -1,19 +1,19 @@ // App's common configuration for any process (main, renderer, build pipeline, etc.) import path from "path"; -import packageInfo from "../../package.json" +import packageInfo from "../../package.json"; import { defineGlobal } from "./utils/defineGlobal"; -export const isMac = process.platform === "darwin" -export const isWindows = process.platform === "win32" -export const isLinux = process.platform === "linux" +export const isMac = process.platform === "darwin"; +export const isWindows = process.platform === "win32"; +export const isLinux = process.platform === "linux"; export const isDebugging = process.env.DEBUG === "true"; -export const isSnap = !!process.env["SNAP"] -export const isProduction = process.env.NODE_ENV === "production" +export const isSnap = !!process.env["SNAP"]; +export const isProduction = process.env.NODE_ENV === "production"; export const isTestEnv = !!process.env.JEST_WORKER_ID; export const isDevelopment = !isTestEnv && !isProduction; -export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}` -export const publicPath = "/build/" +export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}`; +export const publicPath = "/build/"; // Webpack build paths export const contextDir = process.cwd(); @@ -22,7 +22,7 @@ export const mainDir = path.join(contextDir, "src/main"); export const rendererDir = path.join(contextDir, "src/renderer"); export const htmlTemplate = path.resolve(rendererDir, "template.html"); export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss"); -export const webpackDevServerPort = 9009 +export const webpackDevServerPort = 9009; // Special runtime paths defineGlobal("__static", { @@ -30,14 +30,14 @@ defineGlobal("__static", { if (isDevelopment) { return path.resolve(contextDir, "static"); } - return path.resolve(process.resourcesPath, "static") + return path.resolve(process.resourcesPath, "static"); } -}) +}); // Apis -export const apiPrefix = "/api" // local router apis -export const apiKubePrefix = "/api-kube" // k8s cluster apis +export const apiPrefix = "/api"; // local router apis +export const apiKubePrefix = "/api-kube"; // k8s cluster apis // Links -export const issuesTrackerUrl = "https://github.com/lensapp/lens/issues" -export const slackUrl = "https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI" +export const issuesTrackerUrl = "https://github.com/lensapp/lens/issues"; +export const slackUrl = "https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI"; diff --git a/src/common/workspace-store.ts b/src/common/workspace-store.ts index baae6287ab..67e1c4d22a 100644 --- a/src/common/workspace-store.ts +++ b/src/common/workspace-store.ts @@ -1,7 +1,7 @@ import { ipcRenderer } from "electron"; import { action, computed, observable, toJS, reaction } from "mobx"; import { BaseStore } from "./base-store"; -import { clusterStore } from "./cluster-store" +import { clusterStore } from "./cluster-store"; import { appEventBus } from "./event-bus"; import { broadcastMessage } from "../common/ipc"; import logger from "../main/logger"; @@ -25,40 +25,40 @@ export interface WorkspaceState { } export class Workspace implements WorkspaceModel, WorkspaceState { - @observable id: WorkspaceId - @observable name: string - @observable description?: string - @observable ownerRef?: string - @observable enabled: boolean + @observable id: WorkspaceId; + @observable name: string; + @observable description?: string; + @observable ownerRef?: string; + @observable enabled: boolean; constructor(data: WorkspaceModel) { - Object.assign(this, data) + Object.assign(this, data); if (!ipcRenderer) { reaction(() => this.getState(), () => { - this.pushState() - }) + this.pushState(); + }); } } get isManaged(): boolean { - return !!this.ownerRef + return !!this.ownerRef; } getState(): WorkspaceState { return { enabled: this.enabled - } + }; } pushState(state = this.getState()) { - logger.silly("[WORKSPACE] pushing state", {...state, id: this.id}) - broadcastMessage("workspace:state", this.id, toJS(state)) + logger.silly("[WORKSPACE] pushing state", {...state, id: this.id}); + broadcastMessage("workspace:state", this.id, toJS(state)); } @action setState(state: WorkspaceState) { - Object.assign(this, state) + Object.assign(this, state); } toJSON(): WorkspaceModel { @@ -67,12 +67,12 @@ export class Workspace implements WorkspaceModel, WorkspaceState { name: this.name, description: this.description, ownerRef: this.ownerRef - }) + }); } } export class WorkspaceStore extends BaseStore { - static readonly defaultId: WorkspaceId = "default" + static readonly defaultId: WorkspaceId = "default"; private constructor() { super({ @@ -81,21 +81,21 @@ export class WorkspaceStore extends BaseStore { if (!ipcRenderer) { setInterval(() => { - this.pushState() - }, 5000) + this.pushState(); + }, 5000); } } registerIpcListener() { - logger.info("[WORKSPACE-STORE] starting to listen state events") + logger.info("[WORKSPACE-STORE] starting to listen state events"); ipcRenderer.on("workspace:state", (event, workspaceId: string, state: WorkspaceState) => { - this.getById(workspaceId)?.setState(state) - }) + this.getById(workspaceId)?.setState(state); + }); } unregisterIpcListener() { - super.unregisterIpcListener() - ipcRenderer.removeAllListeners("workspace:state") + super.unregisterIpcListener(); + ipcRenderer.removeAllListeners("workspace:state"); } @observable currentWorkspaceId = WorkspaceStore.defaultId; @@ -121,8 +121,8 @@ export class WorkspaceStore extends BaseStore { pushState() { this.workspaces.forEach((w) => { - w.pushState() - }) + w.pushState(); + }); } isDefault(id: WorkspaceId) { @@ -154,7 +154,7 @@ export class WorkspaceStore extends BaseStore { return; } this.workspaces.set(id, workspace); - appEventBus.emit({name: "workspace", action: "add"}) + appEventBus.emit({name: "workspace", action: "add"}); return workspace; } @@ -166,7 +166,7 @@ export class WorkspaceStore extends BaseStore { @action removeWorkspace(workspace: Workspace) { - this.removeWorkspaceById(workspace.id) + this.removeWorkspaceById(workspace.id); } @action @@ -180,24 +180,24 @@ export class WorkspaceStore extends BaseStore { this.currentWorkspaceId = WorkspaceStore.defaultId; // reset to default } this.workspaces.delete(id); - appEventBus.emit({name: "workspace", action: "remove"}) - clusterStore.removeByWorkspaceId(id) + appEventBus.emit({name: "workspace", action: "remove"}); + clusterStore.removeByWorkspaceId(id); } @action protected fromStore({ currentWorkspace, workspaces = [] }: WorkspaceStoreModel) { if (currentWorkspace) { - this.currentWorkspaceId = currentWorkspace + this.currentWorkspaceId = currentWorkspace; } if (workspaces.length) { this.workspaces.clear(); workspaces.forEach(ws => { - const workspace = new Workspace(ws) + const workspace = new Workspace(ws); if (!workspace.isManaged) { - workspace.enabled = true + workspace.enabled = true; } - this.workspaces.set(workspace.id, workspace) - }) + this.workspaces.set(workspace.id, workspace); + }); } } @@ -207,8 +207,8 @@ export class WorkspaceStore extends BaseStore { workspaces: this.workspacesList.map((w) => w.toJSON()), }, { recurseEverything: true - }) + }); } } -export const workspaceStore = WorkspaceStore.getInstance() +export const workspaceStore = WorkspaceStore.getInstance(); diff --git a/src/extensions/__tests__/lens-extension.test.ts b/src/extensions/__tests__/lens-extension.test.ts index c7e9ed5513..d6ba04cbb5 100644 --- a/src/extensions/__tests__/lens-extension.test.ts +++ b/src/extensions/__tests__/lens-extension.test.ts @@ -1,6 +1,6 @@ -import { LensExtension } from "../lens-extension" +import { LensExtension } from "../lens-extension"; -let ext: LensExtension = null +let ext: LensExtension = null; describe("lens extension", () => { beforeEach(async () => { @@ -12,12 +12,12 @@ describe("lens extension", () => { manifestPath: "/this/is/fake/package.json", isBundled: false, isEnabled: true - }) - }) + }); + }); describe("name", () => { it("returns name", () => { - expect(ext.name).toBe("foo-bar") - }) - }) -}) + expect(ext.name).toBe("foo-bar"); + }); + }); +}); diff --git a/src/extensions/cluster-feature.ts b/src/extensions/cluster-feature.ts index 90cbd3a0a9..6381d267cc 100644 --- a/src/extensions/cluster-feature.ts +++ b/src/extensions/cluster-feature.ts @@ -1,11 +1,11 @@ import fs from "fs"; -import path from "path" -import hb from "handlebars" -import { observable } from "mobx" -import { ResourceApplier } from "../main/resource-applier" +import path from "path"; +import hb from "handlebars"; +import { observable } from "mobx"; +import { ResourceApplier } from "../main/resource-applier"; import { Cluster } from "../main/cluster"; import logger from "../main/logger"; -import { app } from "electron" +import { app } from "electron"; import { requestMain } from "../common/ipc"; import { clusterKubectlApplyAllHandler } from "../common/cluster-ipc"; @@ -26,7 +26,7 @@ export abstract class ClusterFeature { installed: false, latestVersion: null, canUpgrade: false - } + }; abstract async install(cluster: Cluster): Promise; @@ -38,9 +38,9 @@ export abstract class ClusterFeature { protected async applyResources(cluster: Cluster, resources: string[]) { if (app) { - await new ResourceApplier(cluster).kubectlApplyAll(resources) + await new ResourceApplier(cluster).kubectlApplyAll(resources); } else { - await requestMain(clusterKubectlApplyAllHandler, cluster.id, resources) + await requestMain(clusterKubectlApplyAllHandler, cluster.id, resources); } } diff --git a/src/extensions/core-api/app.ts b/src/extensions/core-api/app.ts index f3e44ed001..fdd9425b47 100644 --- a/src/extensions/core-api/app.ts +++ b/src/extensions/core-api/app.ts @@ -1,4 +1,4 @@ import { getAppVersion } from "../../common/utils"; -export const version = getAppVersion() -export { isSnap, isWindows, isMac, isLinux, appName, slackUrl, issuesTrackerUrl } from "../../common/vars" \ No newline at end of file +export const version = getAppVersion(); +export { isSnap, isWindows, isMac, isLinux, appName, slackUrl, issuesTrackerUrl } from "../../common/vars"; \ No newline at end of file diff --git a/src/extensions/core-api/cluster-feature.ts b/src/extensions/core-api/cluster-feature.ts index 9f2d3b8a40..170f4543f3 100644 --- a/src/extensions/core-api/cluster-feature.ts +++ b/src/extensions/core-api/cluster-feature.ts @@ -1,2 +1,2 @@ -export { ClusterFeature as Feature } from "../cluster-feature" -export type { ClusterFeatureStatus as FeatureStatus } from "../cluster-feature" +export { ClusterFeature as Feature } from "../cluster-feature"; +export type { ClusterFeatureStatus as FeatureStatus } from "../cluster-feature"; diff --git a/src/extensions/core-api/event-bus.ts b/src/extensions/core-api/event-bus.ts index c958d19129..1a7be58143 100644 --- a/src/extensions/core-api/event-bus.ts +++ b/src/extensions/core-api/event-bus.ts @@ -1,2 +1,2 @@ -export { appEventBus } from "../../common/event-bus" -export type { AppEvent } from "../../common/event-bus" +export { appEventBus } from "../../common/event-bus"; +export type { AppEvent } from "../../common/event-bus"; diff --git a/src/extensions/core-api/index.ts b/src/extensions/core-api/index.ts index dc040a3355..19ede51817 100644 --- a/src/extensions/core-api/index.ts +++ b/src/extensions/core-api/index.ts @@ -1,14 +1,14 @@ // Lens-extensions api developer's kit -export * from "../lens-main-extension" -export * from "../lens-renderer-extension" +export * from "../lens-main-extension"; +export * from "../lens-renderer-extension"; // APIs -import * as App from "./app" -import * as EventBus from "./event-bus" -import * as Store from "./stores" -import * as Util from "./utils" -import * as ClusterFeature from "./cluster-feature" -import * as Interface from "../interfaces" +import * as App from "./app"; +import * as EventBus from "./event-bus"; +import * as Store from "./stores"; +import * as Util from "./utils"; +import * as ClusterFeature from "./cluster-feature"; +import * as Interface from "../interfaces"; export { App, @@ -17,4 +17,4 @@ export { Interface, Store, Util, -} +}; diff --git a/src/extensions/core-api/stores.ts b/src/extensions/core-api/stores.ts index d44536769f..d7e489e5c0 100644 --- a/src/extensions/core-api/stores.ts +++ b/src/extensions/core-api/stores.ts @@ -1,6 +1,6 @@ -export { ExtensionStore } from "../extension-store" -export { clusterStore } from "../../common/cluster-store" -export type { ClusterModel } from "../../common/cluster-store" -export { Cluster } from "../../main/cluster" -export { workspaceStore, Workspace } from "../../common/workspace-store" -export type { WorkspaceModel } from "../../common/workspace-store" +export { ExtensionStore } from "../extension-store"; +export { clusterStore } from "../../common/cluster-store"; +export type { ClusterModel } from "../../common/cluster-store"; +export { Cluster } from "../../main/cluster"; +export { workspaceStore, Workspace } from "../../common/workspace-store"; +export type { WorkspaceModel } from "../../common/workspace-store"; diff --git a/src/extensions/core-api/utils.ts b/src/extensions/core-api/utils.ts index c70959f2ba..c249ff5238 100644 --- a/src/extensions/core-api/utils.ts +++ b/src/extensions/core-api/utils.ts @@ -1,3 +1,3 @@ -export { Singleton, openExternal } from "../../common/utils" -export { prevDefault, stopPropagation } from "../../renderer/utils/prevDefault" -export { cssNames } from "../../renderer/utils/cssNames" +export { Singleton, openExternal } from "../../common/utils"; +export { prevDefault, stopPropagation } from "../../renderer/utils/prevDefault"; +export { cssNames } from "../../renderer/utils/cssNames"; diff --git a/src/extensions/extension-api.ts b/src/extensions/extension-api.ts index b6be0b9f4e..e4a8a77334 100644 --- a/src/extensions/extension-api.ts +++ b/src/extensions/extension-api.ts @@ -1,4 +1,4 @@ // Extension-api types generation bundle -export * from "./core-api" -export * from "./renderer-api" +export * from "./core-api"; +export * from "./renderer-api"; diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts index 643d9658bc..c71fe90db2 100644 --- a/src/extensions/extension-loader.ts +++ b/src/extensions/extension-loader.ts @@ -1,24 +1,24 @@ -import type { LensExtension, LensExtensionConstructor, LensExtensionId } from "./lens-extension" -import type { LensMainExtension } from "./lens-main-extension" -import type { LensRendererExtension } from "./lens-renderer-extension" +import type { LensExtension, LensExtensionConstructor, LensExtensionId } from "./lens-extension"; +import type { LensMainExtension } from "./lens-main-extension"; +import type { LensRendererExtension } from "./lens-renderer-extension"; import type { InstalledExtension } from "./extension-manager"; -import path from "path" -import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc" -import { action, computed, observable, reaction, toJS, when } from "mobx" -import logger from "../main/logger" -import { app, ipcRenderer, remote } from "electron" +import path from "path"; +import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc"; +import { action, computed, observable, reaction, toJS, when } from "mobx"; +import logger from "../main/logger"; +import { app, ipcRenderer, remote } from "electron"; import * as registries from "./registries"; import { extensionsStore } from "./extensions-store"; // lazy load so that we get correct userData export function extensionPackagesRoot() { - return path.join((app || remote.app).getPath("userData")) + return path.join((app || remote.app).getPath("userData")); } export class ExtensionLoader { protected extensions = observable.map(); protected instances = observable.map(); - protected readonly requestExtensionsChannel = "extensions:loaded" + protected readonly requestExtensionsChannel = "extensions:loaded"; @observable isLoaded = false; whenLoaded = when(() => this.isLoaded); @@ -29,22 +29,22 @@ export class ExtensionLoader { if (ext.isBundled) { extensions.delete(extId); } - }) + }); return extensions; } @action async init() { if (ipcRenderer) { - this.initRenderer() + this.initRenderer(); } else { - this.initMain() + this.initMain(); } extensionsStore.manageState(this); } initExtensions(extensions?: Map) { - this.extensions.replace(extensions) + this.extensions.replace(extensions); } protected async initMain() { @@ -53,12 +53,12 @@ export class ExtensionLoader { this.broadcastExtensions(); reaction(() => this.extensions.toJS(), () => { - this.broadcastExtensions() - }) + this.broadcastExtensions(); + }); handleRequest(this.requestExtensionsChannel, () => { - return Array.from(this.toJSON()) - }) + return Array.from(this.toJSON()); + }); } protected async initRenderer() { @@ -66,25 +66,25 @@ export class ExtensionLoader { this.isLoaded = true; extensions.forEach(([extId, ext]) => { if (!this.extensions.has(extId)) { - this.extensions.set(extId, ext) + this.extensions.set(extId, ext); } - }) - } - requestMain(this.requestExtensionsChannel).then(extensionListHandler) + }); + }; + requestMain(this.requestExtensionsChannel).then(extensionListHandler); subscribeToBroadcast(this.requestExtensionsChannel, (event, extensions: [LensExtensionId, InstalledExtension][]) => { - extensionListHandler(extensions) + extensionListHandler(extensions); }); } loadOnMain() { - logger.info('[EXTENSIONS-LOADER]: load on main') + logger.info('[EXTENSIONS-LOADER]: load on main'); this.autoInitExtensions((ext: LensMainExtension) => [ registries.menuRegistry.add(ext.appMenus) ]); } loadOnClusterManagerRenderer() { - logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)') + logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)'); this.autoInitExtensions((ext: LensRendererExtension) => [ registries.globalPageRegistry.add(ext.globalPages, ext), registries.globalPageMenuRegistry.add(ext.globalPageMenus, ext), @@ -95,14 +95,14 @@ export class ExtensionLoader { } loadOnClusterRenderer() { - logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)') + logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)'); this.autoInitExtensions((ext: LensRendererExtension) => [ registries.clusterPageRegistry.add(ext.clusterPages, ext), registries.clusterPageMenuRegistry.add(ext.clusterPageMenus, ext), registries.kubeObjectMenuRegistry.add(ext.kubeObjectMenuItems), registries.kubeObjectDetailRegistry.add(ext.kubeObjectDetailItems), registries.kubeObjectStatusRegistry.add(ext.kubeObjectStatusTexts) - ]) + ]); } protected autoInitExtensions(register: (ext: LensExtension) => Function[]) { @@ -111,43 +111,43 @@ export class ExtensionLoader { let instance = this.instances.get(extId); if (ext.isEnabled && !instance) { try { - const LensExtensionClass: LensExtensionConstructor = this.requireExtension(ext) + const LensExtensionClass: LensExtensionConstructor = this.requireExtension(ext); if (!LensExtensionClass) continue; instance = new LensExtensionClass(ext); instance.whenEnabled(() => register(instance)); instance.enable(); this.instances.set(extId, instance); } catch (err) { - logger.error(`[EXTENSION-LOADER]: activation extension error`, { ext, err }) + logger.error(`[EXTENSION-LOADER]: activation extension error`, { ext, err }); } } else if (!ext.isEnabled && instance) { try { instance.disable(); this.instances.delete(extId); } catch (err) { - logger.error(`[EXTENSION-LOADER]: deactivation extension error`, { ext, err }) + logger.error(`[EXTENSION-LOADER]: deactivation extension error`, { ext, err }); } } } }, { fireImmediately: true, - }) + }); } protected requireExtension(extension: InstalledExtension) { - let extEntrypoint = "" + let extEntrypoint = ""; try { if (ipcRenderer && extension.manifest.renderer) { - extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.renderer)) + extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.renderer)); } else if (!ipcRenderer && extension.manifest.main) { - extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.main)) + extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.main)); } if (extEntrypoint !== "") { return __non_webpack_require__(extEntrypoint).default; } } catch (err) { console.error(`[EXTENSION-LOADER]: can't load extension main at ${extEntrypoint}: ${err}`, { extension }); - console.trace(err) + console.trace(err); } } @@ -159,11 +159,11 @@ export class ExtensionLoader { return toJS(this.extensions, { exportMapsAsObjects: false, recurseEverything: true, - }) + }); } broadcastExtensions() { - broadcastMessage(this.requestExtensionsChannel, Array.from(this.toJSON())) + broadcastMessage(this.requestExtensionsChannel, Array.from(this.toJSON())); } } diff --git a/src/extensions/extension-manager.ts b/src/extensions/extension-manager.ts index 7a10fa35f4..0e51eeb666 100644 --- a/src/extensions/extension-manager.ts +++ b/src/extensions/extension-manager.ts @@ -1,11 +1,11 @@ -import type { LensExtensionId, LensExtensionManifest } from "./lens-extension" -import path from "path" -import os from "os" -import fs from "fs-extra" +import type { LensExtensionId, LensExtensionManifest } from "./lens-extension"; +import path from "path"; +import os from "os"; +import fs from "fs-extra"; import child_process from "child_process"; -import logger from "../main/logger" -import { extensionPackagesRoot } from "./extension-loader" -import { getBundledExtensions } from "../common/utils/app-version" +import logger from "../main/logger"; +import { extensionPackagesRoot } from "./extension-loader"; +import { getBundledExtensions } from "../common/utils/app-version"; export interface InstalledExtension { readonly manifest: LensExtensionManifest; @@ -16,26 +16,26 @@ export interface InstalledExtension { type Dependencies = { [name: string]: string; -} +}; type PackageJson = { dependencies: Dependencies; -} +}; export class ExtensionManager { - protected bundledFolderPath: string + protected bundledFolderPath: string; protected packagesJson: PackageJson = { dependencies: {} - } + }; get extensionPackagesRoot() { - return extensionPackagesRoot() + return extensionPackagesRoot(); } get inTreeTargetPath() { - return path.join(this.extensionPackagesRoot, "extensions") + return path.join(this.extensionPackagesRoot, "extensions"); } get inTreeFolderPath(): string { @@ -43,7 +43,7 @@ export class ExtensionManager { } get nodeModulesPath(): string { - return path.join(this.extensionPackagesRoot, "node_modules") + return path.join(this.extensionPackagesRoot, "node_modules"); } get localFolderPath(): string { @@ -51,30 +51,30 @@ export class ExtensionManager { } get npmPath() { - return __non_webpack_require__.resolve('npm/bin/npm-cli') + return __non_webpack_require__.resolve('npm/bin/npm-cli'); } get packageJsonPath() { - return path.join(this.extensionPackagesRoot, "package.json") + return path.join(this.extensionPackagesRoot, "package.json"); } async load(): Promise> { - logger.info("[EXTENSION-MANAGER] loading extensions from " + this.extensionPackagesRoot) + logger.info("[EXTENSION-MANAGER] loading extensions from " + this.extensionPackagesRoot); if (fs.existsSync(path.join(this.extensionPackagesRoot, "package-lock.json"))) { - await fs.remove(path.join(this.extensionPackagesRoot, "package-lock.json")) + await fs.remove(path.join(this.extensionPackagesRoot, "package-lock.json")); } try { - await fs.access(this.inTreeFolderPath, fs.constants.W_OK) - this.bundledFolderPath = this.inTreeFolderPath + await fs.access(this.inTreeFolderPath, fs.constants.W_OK); + this.bundledFolderPath = this.inTreeFolderPath; } catch { // we need to copy in-tree extensions so that we can symlink them properly on "npm install" - await fs.remove(this.inTreeTargetPath) - await fs.ensureDir(this.inTreeTargetPath) - await fs.copy(this.inTreeFolderPath, this.inTreeTargetPath) - this.bundledFolderPath = this.inTreeTargetPath + await fs.remove(this.inTreeTargetPath); + await fs.ensureDir(this.inTreeTargetPath); + await fs.copy(this.inTreeFolderPath, this.inTreeTargetPath); + this.bundledFolderPath = this.inTreeTargetPath; } - await fs.ensureDir(this.nodeModulesPath) - await fs.ensureDir(this.localFolderPath) + await fs.ensureDir(this.nodeModulesPath); + await fs.ensureDir(this.localFolderPath); return await this.loadExtensions(); } @@ -82,16 +82,16 @@ export class ExtensionManager { let manifestJson: LensExtensionManifest; try { fs.accessSync(manifestPath, fs.constants.F_OK); // check manifest file for existence - manifestJson = __non_webpack_require__(manifestPath) - this.packagesJson.dependencies[manifestJson.name] = path.dirname(manifestPath) + manifestJson = __non_webpack_require__(manifestPath); + this.packagesJson.dependencies[manifestJson.name] = path.dirname(manifestPath); - logger.info("[EXTENSION-MANAGER] installed extension " + manifestJson.name) + logger.info("[EXTENSION-MANAGER] installed extension " + manifestJson.name); return { manifestPath: path.join(this.nodeModulesPath, manifestJson.name, "package.json"), manifest: manifestJson, isBundled: isBundled, isEnabled: isBundled, - } + }; } catch (err) { logger.error(`[EXTENSION-MANAGER]: can't install extension at ${manifestPath}: ${err}`, { manifestJson }); } @@ -102,65 +102,65 @@ export class ExtensionManager { const child = child_process.fork(this.npmPath, ["install", "--silent", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock"], { cwd: extensionPackagesRoot(), silent: true - }) + }); child.on("close", () => { - resolve() - }) + resolve(); + }); child.on("error", (err) => { - reject(err) - }) - }) + reject(err); + }); + }); } async loadExtensions() { - const bundledExtensions = await this.loadBundledExtensions() - const localExtensions = await this.loadFromFolder(this.localFolderPath) - await fs.writeFile(path.join(this.packageJsonPath), JSON.stringify(this.packagesJson, null, 2), { mode: 0o600 }) - await this.installPackages() - const extensions = bundledExtensions.concat(localExtensions) + const bundledExtensions = await this.loadBundledExtensions(); + const localExtensions = await this.loadFromFolder(this.localFolderPath); + await fs.writeFile(path.join(this.packageJsonPath), JSON.stringify(this.packagesJson, null, 2), { mode: 0o600 }); + await this.installPackages(); + const extensions = bundledExtensions.concat(localExtensions); return new Map(extensions.map(ext => [ext.manifestPath, ext])); } async loadBundledExtensions() { - const extensions: InstalledExtension[] = [] - const folderPath = this.bundledFolderPath - const bundledExtensions = getBundledExtensions() + const extensions: InstalledExtension[] = []; + const folderPath = this.bundledFolderPath; + const bundledExtensions = getBundledExtensions(); const paths = await fs.readdir(folderPath); for (const fileName of paths) { if (!bundledExtensions.includes(fileName)) { - continue + continue; } const absPath = path.resolve(folderPath, fileName); const manifestPath = path.resolve(absPath, "package.json"); - const ext = await this.getByManifest(manifestPath, { isBundled: true }).catch(() => null) + const ext = await this.getByManifest(manifestPath, { isBundled: true }).catch(() => null); if (ext) { - extensions.push(ext) + extensions.push(ext); } } logger.debug(`[EXTENSION-MANAGER]: ${extensions.length} extensions loaded`, { folderPath, extensions }); - return extensions + return extensions; } async loadFromFolder(folderPath: string): Promise { - const bundledExtensions = getBundledExtensions() - const extensions: InstalledExtension[] = [] + const bundledExtensions = getBundledExtensions(); + const extensions: InstalledExtension[] = []; const paths = await fs.readdir(folderPath); for (const fileName of paths) { if (bundledExtensions.includes(fileName)) { // do no allow to override bundled extensions - continue + continue; } const absPath = path.resolve(folderPath, fileName); if (!fs.existsSync(absPath)) { - continue + continue; } - const lstat = await fs.lstat(absPath) + const lstat = await fs.lstat(absPath); if (!lstat.isDirectory() && !lstat.isSymbolicLink()) { // skip non-directories - continue + continue; } const manifestPath = path.resolve(absPath, "package.json"); - const ext = await this.getByManifest(manifestPath).catch(() => null) + const ext = await this.getByManifest(manifestPath).catch(() => null); if (ext) { - extensions.push(ext) + extensions.push(ext); } } @@ -169,4 +169,4 @@ export class ExtensionManager { } } -export const extensionManager = new ExtensionManager() +export const extensionManager = new ExtensionManager(); diff --git a/src/extensions/extension-store.ts b/src/extensions/extension-store.ts index ec2f61948e..a8078994ca 100644 --- a/src/extensions/extension-store.ts +++ b/src/extensions/extension-store.ts @@ -1,21 +1,21 @@ -import { BaseStore } from "../common/base-store" -import * as path from "path" -import { LensExtension } from "./lens-extension" +import { BaseStore } from "../common/base-store"; +import * as path from "path"; +import { LensExtension } from "./lens-extension"; export abstract class ExtensionStore extends BaseStore { - protected extension: LensExtension + protected extension: LensExtension; async loadExtension(extension: LensExtension) { - this.extension = extension - return super.load() + this.extension = extension; + return super.load(); } async load() { - if (!this.extension) { return } - return super.load() + if (!this.extension) { return; } + return super.load(); } protected cwd() { - return path.join(super.cwd(), "extension-store", this.extension.name) + return path.join(super.cwd(), "extension-store", this.extension.name); } } diff --git a/src/extensions/extensions-store.ts b/src/extensions/extensions-store.ts index ba942c41d9..1669dd4bcc 100644 --- a/src/extensions/extensions-store.ts +++ b/src/extensions/extensions-store.ts @@ -1,6 +1,6 @@ import type { LensExtensionId } from "./lens-extension"; import type { ExtensionLoader } from "./extension-loader"; -import { BaseStore } from "../common/base-store" +import { BaseStore } from "../common/base-store"; import { action, observable, reaction, toJS } from "mobx"; export interface LensExtensionsStoreModel { @@ -25,9 +25,9 @@ export class ExtensionsStore extends BaseStore { return Array.from(extensionLoader.userExtensions).reduce((state, [extId, ext]) => { state[extId] = { enabled: ext.isEnabled, - } + }; return state; - }, state) + }, state); } async manageState(extensionLoader: ExtensionLoader) { @@ -46,13 +46,13 @@ export class ExtensionsStore extends BaseStore { if (ext && !ext.isBundled) { ext.isEnabled = state.enabled; } - }) - }) + }); + }); // save state on change `extension.isEnabled` reaction(() => this.getState(extensionLoader), extensionsState => { - this.state.merge(extensionsState) - }) + this.state.merge(extensionsState); + }); } isEnabled(extId: LensExtensionId) { @@ -70,7 +70,7 @@ export class ExtensionsStore extends BaseStore { extensions: this.state.toJSON(), }, { recurseEverything: true - }) + }); } } diff --git a/src/extensions/interfaces/index.ts b/src/extensions/interfaces/index.ts index e3612bdb7f..c91d8cdd19 100644 --- a/src/extensions/interfaces/index.ts +++ b/src/extensions/interfaces/index.ts @@ -1 +1 @@ -export * from "./registrations" \ No newline at end of file +export * from "./registrations"; \ No newline at end of file diff --git a/src/extensions/interfaces/registrations.ts b/src/extensions/interfaces/registrations.ts index 14c9f66c22..a2ebb10290 100644 --- a/src/extensions/interfaces/registrations.ts +++ b/src/extensions/interfaces/registrations.ts @@ -1,8 +1,8 @@ -export type { AppPreferenceRegistration, AppPreferenceComponents } from "../registries/app-preference-registry" -export type { ClusterFeatureRegistration, ClusterFeatureComponents } from "../registries/cluster-feature-registry" -export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from "../registries/kube-object-detail-registry" -export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../registries/kube-object-menu-registry" -export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry" -export type { PageRegistration, PageComponents } from "../registries/page-registry" -export type { PageMenuRegistration, PageMenuComponents } from "../registries/page-menu-registry" -export type { StatusBarRegistration } from "../registries/status-bar-registry" \ No newline at end of file +export type { AppPreferenceRegistration, AppPreferenceComponents } from "../registries/app-preference-registry"; +export type { ClusterFeatureRegistration, ClusterFeatureComponents } from "../registries/cluster-feature-registry"; +export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from "../registries/kube-object-detail-registry"; +export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../registries/kube-object-menu-registry"; +export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry"; +export type { PageRegistration, PageComponents } from "../registries/page-registry"; +export type { PageMenuRegistration, PageMenuComponents } from "../registries/page-menu-registry"; +export type { StatusBarRegistration } from "../registries/status-bar-registry"; \ No newline at end of file diff --git a/src/extensions/lens-extension.ts b/src/extensions/lens-extension.ts index f1ffb9184b..444cf449d6 100644 --- a/src/extensions/lens-extension.ts +++ b/src/extensions/lens-extension.ts @@ -21,9 +21,9 @@ export class LensExtension { @observable private isEnabled = false; constructor({ manifest, manifestPath, isBundled }: InstalledExtension) { - this.manifest = manifest - this.manifestPath = manifestPath - this.isBundled = !!isBundled + this.manifest = manifest; + this.manifestPath = manifestPath; + this.isBundled = !!isBundled; } get id(): LensExtensionId { @@ -31,15 +31,15 @@ export class LensExtension { } get name() { - return this.manifest.name + return this.manifest.name; } get version() { - return this.manifest.version + return this.manifest.version; } get description() { - return this.manifest.description + return this.manifest.description; } @action @@ -60,18 +60,18 @@ export class LensExtension { toggle(enable?: boolean) { if (typeof enable === "boolean") { - enable ? this.enable() : this.disable() + enable ? this.enable() : this.disable(); } else { - this.isEnabled ? this.disable() : this.enable() + this.isEnabled ? this.disable() : this.enable(); } } async whenEnabled(handlers: () => Function[]) { const disposers: Function[] = []; const unregisterHandlers = () => { - disposers.forEach(unregister => unregister()) + disposers.forEach(unregister => unregister()); disposers.length = 0; - } + }; const cancelReaction = reaction(() => this.isEnabled, isEnabled => { if (isEnabled) { disposers.push(...handlers()); @@ -80,11 +80,11 @@ export class LensExtension { } }, { fireImmediately: true - }) + }); return () => { unregisterHandlers(); cancelReaction(); - } + }; } protected onActivate() { diff --git a/src/extensions/lens-main-extension.ts b/src/extensions/lens-main-extension.ts index af091e0c1c..b425c5bf46 100644 --- a/src/extensions/lens-main-extension.ts +++ b/src/extensions/lens-main-extension.ts @@ -1,11 +1,11 @@ import type { MenuRegistration } from "./registries/menu-registry"; import { observable } from "mobx"; -import { LensExtension } from "./lens-extension" +import { LensExtension } from "./lens-extension"; import { WindowManager } from "../main/window-manager"; -import { getExtensionPageUrl } from "./registries/page-registry" +import { getExtensionPageUrl } from "./registries/page-registry"; export class LensMainExtension extends LensExtension { - @observable.shallow appMenus: MenuRegistration[] = [] + @observable.shallow appMenus: MenuRegistration[] = []; async navigate

(pageId?: string, params?: P, frameId?: number) { const windowManager = WindowManager.getInstance(); diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index 0fb346e1a1..56ed90684f 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -1,19 +1,19 @@ -import type { AppPreferenceRegistration, ClusterFeatureRegistration, KubeObjectDetailRegistration, KubeObjectMenuRegistration, KubeObjectStatusRegistration, PageMenuRegistration, PageRegistration, StatusBarRegistration, } from "./registries" +import type { AppPreferenceRegistration, ClusterFeatureRegistration, KubeObjectDetailRegistration, KubeObjectMenuRegistration, KubeObjectStatusRegistration, PageMenuRegistration, PageRegistration, StatusBarRegistration, } from "./registries"; import { observable } from "mobx"; -import { LensExtension } from "./lens-extension" -import { getExtensionPageUrl } from "./registries/page-registry" +import { LensExtension } from "./lens-extension"; +import { getExtensionPageUrl } from "./registries/page-registry"; export class LensRendererExtension extends LensExtension { - @observable.shallow globalPages: PageRegistration[] = [] - @observable.shallow clusterPages: PageRegistration[] = [] - @observable.shallow globalPageMenus: PageMenuRegistration[] = [] - @observable.shallow clusterPageMenus: PageMenuRegistration[] = [] - @observable.shallow kubeObjectStatusTexts: KubeObjectStatusRegistration[] = [] - @observable.shallow appPreferences: AppPreferenceRegistration[] = [] - @observable.shallow clusterFeatures: ClusterFeatureRegistration[] = [] - @observable.shallow statusBarItems: StatusBarRegistration[] = [] - @observable.shallow kubeObjectDetailItems: KubeObjectDetailRegistration[] = [] - @observable.shallow kubeObjectMenuItems: KubeObjectMenuRegistration[] = [] + @observable.shallow globalPages: PageRegistration[] = []; + @observable.shallow clusterPages: PageRegistration[] = []; + @observable.shallow globalPageMenus: PageMenuRegistration[] = []; + @observable.shallow clusterPageMenus: PageMenuRegistration[] = []; + @observable.shallow kubeObjectStatusTexts: KubeObjectStatusRegistration[] = []; + @observable.shallow appPreferences: AppPreferenceRegistration[] = []; + @observable.shallow clusterFeatures: ClusterFeatureRegistration[] = []; + @observable.shallow statusBarItems: StatusBarRegistration[] = []; + @observable.shallow kubeObjectDetailItems: KubeObjectDetailRegistration[] = []; + @observable.shallow kubeObjectMenuItems: KubeObjectMenuRegistration[] = []; async navigate

(pageId?: string, params?: P) { const { navigate } = await import("../renderer/navigation"); diff --git a/src/extensions/registries/__tests__/page-registry.test.ts b/src/extensions/registries/__tests__/page-registry.test.ts index 47a5f82d9d..29e60dccc0 100644 --- a/src/extensions/registries/__tests__/page-registry.test.ts +++ b/src/extensions/registries/__tests__/page-registry.test.ts @@ -1,8 +1,8 @@ -import { getExtensionPageUrl, globalPageRegistry, PageRegistration } from "../page-registry" -import { LensExtension } from "../../lens-extension" +import { getExtensionPageUrl, globalPageRegistry, PageRegistration } from "../page-registry"; +import { LensExtension } from "../../lens-extension"; import React from "react"; -let ext: LensExtension = null +let ext: LensExtension = null; describe("getPageUrl", () => { beforeEach(async () => { @@ -14,25 +14,25 @@ describe("getPageUrl", () => { manifestPath: "/this/is/fake/package.json", isBundled: false, isEnabled: true - }) - }) + }); + }); it("returns a page url for extension", () => { - expect(getExtensionPageUrl({ extensionId: ext.name })).toBe("/extension/foo-bar") - }) + expect(getExtensionPageUrl({ extensionId: ext.name })).toBe("/extension/foo-bar"); + }); it("allows to pass base url as parameter", () => { - expect(getExtensionPageUrl({ extensionId: ext.name, pageId: "/test" })).toBe("/extension/foo-bar/test") - }) + expect(getExtensionPageUrl({ extensionId: ext.name, pageId: "/test" })).toBe("/extension/foo-bar/test"); + }); it("removes @", () => { - expect(getExtensionPageUrl({ extensionId: "@foo/bar" })).toBe("/extension/foo-bar") - }) + expect(getExtensionPageUrl({ extensionId: "@foo/bar" })).toBe("/extension/foo-bar"); + }); it("adds / prefix", () => { - expect(getExtensionPageUrl({ extensionId: ext.name, pageId: "test" })).toBe("/extension/foo-bar/test") - }) -}) + expect(getExtensionPageUrl({ extensionId: ext.name, pageId: "test" })).toBe("/extension/foo-bar/test"); + }); +}); describe("globalPageRegistry", () => { beforeEach(async () => { @@ -44,7 +44,7 @@ describe("globalPageRegistry", () => { manifestPath: "/this/is/fake/package.json", isBundled: false, isEnabled: true - }) + }); globalPageRegistry.add([ { id: "test-page", @@ -63,12 +63,12 @@ describe("globalPageRegistry", () => { Page: () => React.createElement('Default') } }, - ], ext) - }) + ], ext); + }); describe("getByPageMenuTarget", () => { it("matching to first registered page without id", () => { - const page = globalPageRegistry.getByPageMenuTarget({ extensionId: ext.name }) + const page = globalPageRegistry.getByPageMenuTarget({ extensionId: ext.name }); expect(page.id).toEqual(undefined); expect(page.extensionId).toEqual(ext.name); expect(page.routePath).toEqual(getExtensionPageUrl({ extensionId: ext.name })); @@ -78,16 +78,16 @@ describe("globalPageRegistry", () => { const page = globalPageRegistry.getByPageMenuTarget({ pageId: "test-page", extensionId: ext.name - }) - expect(page.id).toEqual("test-page") - }) + }); + expect(page.id).toEqual("test-page"); + }); it("returns null if target not found", () => { const page = globalPageRegistry.getByPageMenuTarget({ pageId: "wrong-page", extensionId: ext.name - }) - expect(page).toBeNull() - }) - }) -}) + }); + expect(page).toBeNull(); + }); + }); +}); diff --git a/src/extensions/registries/app-preference-registry.ts b/src/extensions/registries/app-preference-registry.ts index 6c54911f82..338f93b5bc 100644 --- a/src/extensions/registries/app-preference-registry.ts +++ b/src/extensions/registries/app-preference-registry.ts @@ -1,4 +1,4 @@ -import type React from "react" +import type React from "react"; import { BaseRegistry } from "./base-registry"; export interface AppPreferenceComponents { @@ -14,4 +14,4 @@ export interface AppPreferenceRegistration { export class AppPreferenceRegistry extends BaseRegistry { } -export const appPreferenceRegistry = new AppPreferenceRegistry() +export const appPreferenceRegistry = new AppPreferenceRegistry(); diff --git a/src/extensions/registries/base-registry.ts b/src/extensions/registries/base-registry.ts index e82c9d11bf..73dbd373f0 100644 --- a/src/extensions/registries/base-registry.ts +++ b/src/extensions/registries/base-registry.ts @@ -12,7 +12,7 @@ export class BaseRegistry { add(items: T | T[], ext?: LensExtension): () => void; // allow method overloading with required "ext" @action add(items: T | T[]) { - const normalizedItems = (Array.isArray(items) ? items : [items]) + const normalizedItems = (Array.isArray(items) ? items : [items]); this.items.push(...normalizedItems); return () => this.remove(...normalizedItems); } @@ -21,6 +21,6 @@ export class BaseRegistry { remove(...items: T[]) { items.forEach(item => { this.items.remove(item); // works because of {deep: false}; - }) + }); } } diff --git a/src/extensions/registries/cluster-feature-registry.ts b/src/extensions/registries/cluster-feature-registry.ts index 0e3363d0f0..5017ad27a6 100644 --- a/src/extensions/registries/cluster-feature-registry.ts +++ b/src/extensions/registries/cluster-feature-registry.ts @@ -1,4 +1,4 @@ -import type React from "react" +import type React from "react"; import { BaseRegistry } from "./base-registry"; import { ClusterFeature } from "../cluster-feature"; @@ -15,4 +15,4 @@ export interface ClusterFeatureRegistration { export class ClusterFeatureRegistry extends BaseRegistry { } -export const clusterFeatureRegistry = new ClusterFeatureRegistry() +export const clusterFeatureRegistry = new ClusterFeatureRegistry(); diff --git a/src/extensions/registries/index.ts b/src/extensions/registries/index.ts index cdcfb7124b..8e343742ec 100644 --- a/src/extensions/registries/index.ts +++ b/src/extensions/registries/index.ts @@ -1,11 +1,11 @@ // All registries managed by extensions api -export * from "./page-registry" -export * from "./page-menu-registry" -export * from "./menu-registry" -export * from "./app-preference-registry" -export * from "./status-bar-registry" +export * from "./page-registry"; +export * from "./page-menu-registry"; +export * from "./menu-registry"; +export * from "./app-preference-registry"; +export * from "./status-bar-registry"; export * from "./kube-object-detail-registry"; export * from "./kube-object-menu-registry"; -export * from "./cluster-feature-registry" -export * from "./kube-object-status-registry" +export * from "./cluster-feature-registry"; +export * from "./kube-object-status-registry"; diff --git a/src/extensions/registries/kube-object-detail-registry.ts b/src/extensions/registries/kube-object-detail-registry.ts index 32fea66b81..2638e82ade 100644 --- a/src/extensions/registries/kube-object-detail-registry.ts +++ b/src/extensions/registries/kube-object-detail-registry.ts @@ -1,4 +1,4 @@ -import React from "react" +import React from "react"; import { BaseRegistry } from "./base-registry"; export interface KubeObjectDetailComponents { @@ -15,15 +15,15 @@ export interface KubeObjectDetailRegistration { export class KubeObjectDetailRegistry extends BaseRegistry { getItemsForKind(kind: string, apiVersion: string) { const items = this.getItems().filter((item) => { - return item.kind === kind && item.apiVersions.includes(apiVersion) + return item.kind === kind && item.apiVersions.includes(apiVersion); }).map((item) => { if (item.priority === null) { - item.priority = 50 + item.priority = 50; } - return item - }) - return items.sort((a, b) => b.priority - a.priority) + return item; + }); + return items.sort((a, b) => b.priority - a.priority); } } -export const kubeObjectDetailRegistry = new KubeObjectDetailRegistry() +export const kubeObjectDetailRegistry = new KubeObjectDetailRegistry(); diff --git a/src/extensions/registries/kube-object-menu-registry.ts b/src/extensions/registries/kube-object-menu-registry.ts index 8f527d6a3d..25901f66ad 100644 --- a/src/extensions/registries/kube-object-menu-registry.ts +++ b/src/extensions/registries/kube-object-menu-registry.ts @@ -1,4 +1,4 @@ -import React from "react" +import React from "react"; import { BaseRegistry } from "./base-registry"; export interface KubeObjectMenuComponents { @@ -14,9 +14,9 @@ export interface KubeObjectMenuRegistration { export class KubeObjectMenuRegistry extends BaseRegistry { getItemsForKind(kind: string, apiVersion: string) { return this.getItems().filter((item) => { - return item.kind === kind && item.apiVersions.includes(apiVersion) - }) + return item.kind === kind && item.apiVersions.includes(apiVersion); + }); } } -export const kubeObjectMenuRegistry = new KubeObjectMenuRegistry() +export const kubeObjectMenuRegistry = new KubeObjectMenuRegistry(); diff --git a/src/extensions/registries/kube-object-status-registry.ts b/src/extensions/registries/kube-object-status-registry.ts index 74fd8145d2..5f7aab8d5d 100644 --- a/src/extensions/registries/kube-object-status-registry.ts +++ b/src/extensions/registries/kube-object-status-registry.ts @@ -10,8 +10,8 @@ export interface KubeObjectStatusRegistration { export class KubeObjectStatusRegistry extends BaseRegistry { getItemsForKind(kind: string, apiVersion: string) { return this.getItems().filter((item) => { - return item.kind === kind && item.apiVersions.includes(apiVersion) - }) + return item.kind === kind && item.apiVersions.includes(apiVersion); + }); } } diff --git a/src/extensions/registries/page-menu-registry.ts b/src/extensions/registries/page-menu-registry.ts index ebaaa42dbb..15f11139e6 100644 --- a/src/extensions/registries/page-menu-registry.ts +++ b/src/extensions/registries/page-menu-registry.ts @@ -29,8 +29,8 @@ export class PageMenuRegistry extends BaseRegistry({ extensionId, pageId = "", params }: PageMenuTarget

): string { @@ -68,13 +68,13 @@ export class PageRegistry extends BaseRegistry ...page, extensionId: ext.name, routePath: getExtensionPageUrl({ extensionId: ext.name, pageId: page.id ?? page.routePath }), - })) + })); } catch (err) { logger.error(`[EXTENSION]: page-registration failed`, { items, extension: ext, error: String(err), - }) + }); } return super.add(registeredPages); } diff --git a/src/extensions/renderer-api/components.ts b/src/extensions/renderer-api/components.ts index c051ce13e3..242799c749 100644 --- a/src/extensions/renderer-api/components.ts +++ b/src/extensions/renderer-api/components.ts @@ -1,36 +1,36 @@ // Common UI components // layouts -export * from "../../renderer/components/layout/page-layout" -export * from "../../renderer/components/layout/wizard-layout" -export * from "../../renderer/components/layout/tab-layout" +export * from "../../renderer/components/layout/page-layout"; +export * from "../../renderer/components/layout/wizard-layout"; +export * from "../../renderer/components/layout/tab-layout"; // form-controls -export * from "../../renderer/components/button" -export * from "../../renderer/components/checkbox" -export * from "../../renderer/components/radio" -export * from "../../renderer/components/select" -export * from "../../renderer/components/slider" -export * from "../../renderer/components/input/input" +export * from "../../renderer/components/button"; +export * from "../../renderer/components/checkbox"; +export * from "../../renderer/components/radio"; +export * from "../../renderer/components/select"; +export * from "../../renderer/components/slider"; +export * from "../../renderer/components/input/input"; // other components -export * from "../../renderer/components/icon" -export * from "../../renderer/components/tooltip" -export * from "../../renderer/components/tabs" -export * from "../../renderer/components/table" -export * from "../../renderer/components/badge" -export * from "../../renderer/components/drawer" -export * from "../../renderer/components/dialog" +export * from "../../renderer/components/icon"; +export * from "../../renderer/components/tooltip"; +export * from "../../renderer/components/tabs"; +export * from "../../renderer/components/table"; +export * from "../../renderer/components/badge"; +export * from "../../renderer/components/drawer"; +export * from "../../renderer/components/dialog"; export * from "../../renderer/components/confirm-dialog"; -export * from "../../renderer/components/line-progress" -export * from "../../renderer/components/menu" -export * from "../../renderer/components/notifications" -export * from "../../renderer/components/spinner" -export * from "../../renderer/components/stepper" +export * from "../../renderer/components/line-progress"; +export * from "../../renderer/components/menu"; +export * from "../../renderer/components/notifications"; +export * from "../../renderer/components/spinner"; +export * from "../../renderer/components/stepper"; // kube helpers -export * from "../../renderer/components/kube-object" -export * from "../../renderer/components/+events/kube-event-details" +export * from "../../renderer/components/kube-object"; +export * from "../../renderer/components/+events/kube-event-details"; // specific exports export * from "../../renderer/components/status-brick"; diff --git a/src/extensions/renderer-api/index.ts b/src/extensions/renderer-api/index.ts index 009f49c366..c8e14c0951 100644 --- a/src/extensions/renderer-api/index.ts +++ b/src/extensions/renderer-api/index.ts @@ -1,14 +1,14 @@ // Lens-extensions apis, required in renderer process runtime // APIs -import * as Component from "./components" -import * as K8sApi from "./k8s-api" -import * as Navigation from "./navigation" -import * as Theme from "./theming" +import * as Component from "./components"; +import * as K8sApi from "./k8s-api"; +import * as Navigation from "./navigation"; +import * as Theme from "./theming"; export { Component, K8sApi, Navigation, Theme, -} +}; diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index 2a26b49cdd..fe04550fb7 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -1,6 +1,6 @@ -export { isAllowedResource } from "../../common/rbac" +export { isAllowedResource } from "../../common/rbac"; export { apiManager } from "../../renderer/api/api-manager"; -export { KubeObjectStore } from "../../renderer/kube-object.store" +export { KubeObjectStore } from "../../renderer/kube-object.store"; export { KubeApi, forCluster, IKubeApiCluster } from "../../renderer/api/kube-api"; export { KubeObject } from "../../renderer/api/kube-object"; export { Pod, podsApi, PodsApi, IPodContainer, IPodContainerStatus } from "../../renderer/api/endpoints"; @@ -31,33 +31,33 @@ export { RoleBinding, roleBindingApi } from "../../renderer/api/endpoints"; export { ClusterRole, clusterRoleApi } from "../../renderer/api/endpoints"; export { ClusterRoleBinding, clusterRoleBindingApi } from "../../renderer/api/endpoints"; export { CustomResourceDefinition, crdApi } from "../../renderer/api/endpoints"; -export { KubeObjectStatus, KubeObjectStatusLevel } from "./kube-object-status" +export { KubeObjectStatus, KubeObjectStatusLevel } from "./kube-object-status"; // stores -export type { EventStore } from "../../renderer/components/+events/event.store" -export type { PodsStore } from "../../renderer/components/+workloads-pods/pods.store" -export type { NodesStore } from "../../renderer/components/+nodes/nodes.store" -export type { DeploymentStore } from "../../renderer/components/+workloads-deployments/deployments.store" -export type { DaemonSetStore } from "../../renderer/components/+workloads-daemonsets/daemonsets.store" -export type { StatefulSetStore } from "../../renderer/components/+workloads-statefulsets/statefulset.store" -export type { JobStore } from "../../renderer/components/+workloads-jobs/job.store" -export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/cronjob.store" -export type { ConfigMapsStore } from "../../renderer/components/+config-maps/config-maps.store" -export type { SecretsStore } from "../../renderer/components/+config-secrets/secrets.store" -export type { ReplicaSetStore } from "../../renderer/components/+workloads-replicasets/replicasets.store" -export type { ResourceQuotasStore } from "../../renderer/components/+config-resource-quotas/resource-quotas.store" -export type { HPAStore } from "../../renderer/components/+config-autoscalers/hpa.store" -export type { PodDisruptionBudgetsStore } from "../../renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.store" -export type { ServiceStore } from "../../renderer/components/+network-services/services.store" -export type { EndpointStore } from "../../renderer/components/+network-endpoints/endpoints.store" -export type { IngressStore } from "../../renderer/components/+network-ingresses/ingress.store" -export type { NetworkPolicyStore } from "../../renderer/components/+network-policies/network-policy.store" -export type { PersistentVolumesStore } from "../../renderer/components/+storage-volumes/volumes.store" -export type { VolumeClaimStore } from "../../renderer/components/+storage-volume-claims/volume-claim.store" -export type { StorageClassStore } from "../../renderer/components/+storage-classes/storage-class.store" -export type { NamespaceStore } from "../../renderer/components/+namespaces/namespace.store" -export type { ServiceAccountsStore } from "../../renderer/components/+user-management-service-accounts/service-accounts.store" -export type { RolesStore } from "../../renderer/components/+user-management-roles/roles.store" -export type { RoleBindingsStore } from "../../renderer/components/+user-management-roles-bindings/role-bindings.store" -export type { CRDStore } from "../../renderer/components/+custom-resources/crd.store" -export type { CRDResourceStore } from "../../renderer/components/+custom-resources/crd-resource.store" +export type { EventStore } from "../../renderer/components/+events/event.store"; +export type { PodsStore } from "../../renderer/components/+workloads-pods/pods.store"; +export type { NodesStore } from "../../renderer/components/+nodes/nodes.store"; +export type { DeploymentStore } from "../../renderer/components/+workloads-deployments/deployments.store"; +export type { DaemonSetStore } from "../../renderer/components/+workloads-daemonsets/daemonsets.store"; +export type { StatefulSetStore } from "../../renderer/components/+workloads-statefulsets/statefulset.store"; +export type { JobStore } from "../../renderer/components/+workloads-jobs/job.store"; +export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/cronjob.store"; +export type { ConfigMapsStore } from "../../renderer/components/+config-maps/config-maps.store"; +export type { SecretsStore } from "../../renderer/components/+config-secrets/secrets.store"; +export type { ReplicaSetStore } from "../../renderer/components/+workloads-replicasets/replicasets.store"; +export type { ResourceQuotasStore } from "../../renderer/components/+config-resource-quotas/resource-quotas.store"; +export type { HPAStore } from "../../renderer/components/+config-autoscalers/hpa.store"; +export type { PodDisruptionBudgetsStore } from "../../renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.store"; +export type { ServiceStore } from "../../renderer/components/+network-services/services.store"; +export type { EndpointStore } from "../../renderer/components/+network-endpoints/endpoints.store"; +export type { IngressStore } from "../../renderer/components/+network-ingresses/ingress.store"; +export type { NetworkPolicyStore } from "../../renderer/components/+network-policies/network-policy.store"; +export type { PersistentVolumesStore } from "../../renderer/components/+storage-volumes/volumes.store"; +export type { VolumeClaimStore } from "../../renderer/components/+storage-volume-claims/volume-claim.store"; +export type { StorageClassStore } from "../../renderer/components/+storage-classes/storage-class.store"; +export type { NamespaceStore } from "../../renderer/components/+namespaces/namespace.store"; +export type { ServiceAccountsStore } from "../../renderer/components/+user-management-service-accounts/service-accounts.store"; +export type { RolesStore } from "../../renderer/components/+user-management-roles/roles.store"; +export type { RoleBindingsStore } from "../../renderer/components/+user-management-roles-bindings/role-bindings.store"; +export type { CRDStore } from "../../renderer/components/+custom-resources/crd.store"; +export type { CRDResourceStore } from "../../renderer/components/+custom-resources/crd-resource.store"; diff --git a/src/extensions/renderer-api/kube-object-status.ts b/src/extensions/renderer-api/kube-object-status.ts index 22994ee85d..f609d736fe 100644 --- a/src/extensions/renderer-api/kube-object-status.ts +++ b/src/extensions/renderer-api/kube-object-status.ts @@ -2,7 +2,7 @@ export type KubeObjectStatus = { level: KubeObjectStatusLevel; text: string; timestamp?: string; -} +}; export enum KubeObjectStatusLevel { INFO = 1, diff --git a/src/extensions/renderer-api/navigation.ts b/src/extensions/renderer-api/navigation.ts index f923f6e152..a1191a4b30 100644 --- a/src/extensions/renderer-api/navigation.ts +++ b/src/extensions/renderer-api/navigation.ts @@ -1,3 +1,3 @@ export { navigate } from "../../renderer/navigation"; -export { hideDetails, showDetails, getDetailsUrl } from "../../renderer/navigation" +export { hideDetails, showDetails, getDetailsUrl } from "../../renderer/navigation"; export { IURLParams } from "../../common/utils/buildUrl"; diff --git a/src/jest.setup.ts b/src/jest.setup.ts index 08727bc910..7b4732930e 100644 --- a/src/jest.setup.ts +++ b/src/jest.setup.ts @@ -1,4 +1,4 @@ -import fetchMock from "jest-fetch-mock" +import fetchMock from "jest-fetch-mock"; // rewire global.fetch to call 'fetchMock' fetchMock.enableMocks(); diff --git a/src/main/__test__/cluster.test.ts b/src/main/__test__/cluster.test.ts index 1fb92ed4bc..95177408af 100644 --- a/src/main/__test__/cluster.test.ts +++ b/src/main/__test__/cluster.test.ts @@ -21,35 +21,35 @@ jest.mock("winston", () => ({ Console: jest.fn(), File: jest.fn(), } -})) +})); -jest.mock("../../common/ipc") -jest.mock("../context-handler") -jest.mock("request") -jest.mock("request-promise-native") +jest.mock("../../common/ipc"); +jest.mock("../context-handler"); +jest.mock("request"); +jest.mock("request-promise-native"); import { Console } from "console"; import mockFs from "mock-fs"; import { workspaceStore } from "../../common/workspace-store"; -import { Cluster } from "../cluster" +import { Cluster } from "../cluster"; import { ContextHandler } from "../context-handler"; import { getFreePort } from "../port"; import { V1ResourceAttributes } from "@kubernetes/client-node"; import { apiResources } from "../../common/rbac"; -import request from "request-promise-native" +import request from "request-promise-native"; import { Kubectl } from "../kubectl"; -const mockedRequest = request as jest.MockedFunction +const mockedRequest = request as jest.MockedFunction; -console = new Console(process.stdout, process.stderr) // fix mockFS +console = new Console(process.stdout, process.stderr); // fix mockFS describe("create clusters", () => { beforeEach(() => { - jest.clearAllMocks() - }) + jest.clearAllMocks(); + }); - let c: Cluster + let c: Cluster; beforeEach(() => { const mockOpts = { @@ -74,68 +74,68 @@ describe("create clusters", () => { kind: "Config", preferences: {}, }) - } - mockFs(mockOpts) - jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValue(Promise.resolve(true)) + }; + mockFs(mockOpts); + jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValue(Promise.resolve(true)); c = new Cluster({ id: "foo", contextName: "minikube", kubeConfigPath: "minikube-config.yml", workspace: workspaceStore.currentWorkspaceId - }) - }) + }); + }); afterEach(() => { - mockFs.restore() - }) + mockFs.restore(); + }); it("should be able to create a cluster from a cluster model and apiURL should be decoded", () => { - expect(c.apiUrl).toBe("https://192.168.64.3:8443") - }) + expect(c.apiUrl).toBe("https://192.168.64.3:8443"); + }); it("reconnect should not throw if contextHandler is missing", () => { - expect(() => c.reconnect()).not.toThrowError() - }) + expect(() => c.reconnect()).not.toThrowError(); + }); it("disconnect should not throw if contextHandler is missing", () => { - expect(() => c.disconnect()).not.toThrowError() - }) + expect(() => c.disconnect()).not.toThrowError(); + }); it("init should not throw if everything is in order", async () => { - await c.init(await getFreePort()) + await c.init(await getFreePort()); expect(logger.info).toBeCalledWith(expect.stringContaining("init success"), { id: "foo", apiUrl: "https://192.168.64.3:8443", context: "minikube", - }) - }) + }); + }); it("activating cluster should try to connect to cluster and do a refresh", async () => { - const port = await getFreePort() + const port = await getFreePort(); jest.spyOn(ContextHandler.prototype, "ensureServer"); - const mockListNSs = jest.fn() + const mockListNSs = jest.fn(); const mockKC = { makeApiClient() { return { listNamespace: mockListNSs, - } + }; } - } - jest.spyOn(Cluster.prototype, "isClusterAdmin").mockReturnValue(Promise.resolve(true)) + }; + jest.spyOn(Cluster.prototype, "isClusterAdmin").mockReturnValue(Promise.resolve(true)); jest.spyOn(Cluster.prototype, "canI") .mockImplementationOnce((attr: V1ResourceAttributes): Promise => { - expect(attr.namespace).toBe("default") - expect(attr.resource).toBe("pods") - expect(attr.verb).toBe("list") - return Promise.resolve(true) + expect(attr.namespace).toBe("default"); + expect(attr.resource).toBe("pods"); + expect(attr.verb).toBe("list"); + return Promise.resolve(true); }) .mockImplementation((attr: V1ResourceAttributes): Promise => { - expect(attr.namespace).toBe("default") - expect(attr.verb).toBe("list") - return Promise.resolve(true) - }) - jest.spyOn(Cluster.prototype, "getProxyKubeconfig").mockReturnValue(mockKC as any) + expect(attr.namespace).toBe("default"); + expect(attr.verb).toBe("list"); + return Promise.resolve(true); + }); + jest.spyOn(Cluster.prototype, "getProxyKubeconfig").mockReturnValue(mockKC as any); mockListNSs.mockImplementationOnce(() => ({ body: { items: [{ @@ -144,36 +144,36 @@ describe("create clusters", () => { } }] } - })) + })); mockedRequest.mockImplementationOnce(((uri: any, _options: any) => { - expect(uri).toBe(`http://localhost:${port}/api-kube/version`) - return Promise.resolve({ gitVersion: "1.2.3" }) - }) as any) + expect(uri).toBe(`http://localhost:${port}/api-kube/version`); + return Promise.resolve({ gitVersion: "1.2.3" }); + }) as any); const c = new class extends Cluster { // only way to mock protected methods, without these we leak promises protected bindEvents() { - return + return; } protected async ensureKubectl() { - return Promise.resolve(true) + return Promise.resolve(true); } }({ id: "foo", contextName: "minikube", kubeConfigPath: "minikube-config.yml", workspace: workspaceStore.currentWorkspaceId - }) - await c.init(port) - await c.activate() + }); + await c.init(port); + await c.activate(); - expect(ContextHandler.prototype.ensureServer).toBeCalled() - expect(mockedRequest).toBeCalled() - expect(c.accessible).toBe(true) - expect(c.allowedNamespaces.length).toBe(1) - expect(c.allowedResources.length).toBe(apiResources.length) - c.disconnect() - jest.resetAllMocks() - }) -}) + expect(ContextHandler.prototype.ensureServer).toBeCalled(); + expect(mockedRequest).toBeCalled(); + expect(c.accessible).toBe(true); + expect(c.allowedNamespaces.length).toBe(1); + expect(c.allowedResources.length).toBe(apiResources.length); + c.disconnect(); + jest.resetAllMocks(); + }); +}); diff --git a/src/main/__test__/kube-auth-proxy.test.ts b/src/main/__test__/kube-auth-proxy.test.ts index 8ef1f058e7..dbb3e308e3 100644 --- a/src/main/__test__/kube-auth-proxy.test.ts +++ b/src/main/__test__/kube-auth-proxy.test.ts @@ -21,109 +21,109 @@ jest.mock("winston", () => ({ Console: jest.fn(), File: jest.fn(), } -})) +})); -jest.mock("../../common/ipc") -jest.mock("child_process") -jest.mock("tcp-port-used") +jest.mock("../../common/ipc"); +jest.mock("child_process"); +jest.mock("tcp-port-used"); -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 { bundledKubectlPath, Kubectl } from "../kubectl" +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 { bundledKubectlPath, Kubectl } from "../kubectl"; import { mock, MockProxy } from 'jest-mock-extended'; import { waitUntilUsed } from 'tcp-port-used'; -import { Readable } from "stream" +import { Readable } from "stream"; -const mockBroadcastIpc = broadcastMessage as jest.MockedFunction -const mockSpawn = spawn as jest.MockedFunction -const mockWaitUntilUsed = waitUntilUsed as jest.MockedFunction +const mockBroadcastIpc = broadcastMessage as jest.MockedFunction; +const mockSpawn = spawn as jest.MockedFunction; +const mockWaitUntilUsed = waitUntilUsed as jest.MockedFunction; describe("kube auth proxy tests", () => { beforeEach(() => { - jest.clearAllMocks() - }) + jest.clearAllMocks(); + }); it("calling exit multiple times shouldn't throw", async () => { - const port = await getFreePort() - const kap = new KubeAuthProxy(new Cluster({ id: "foobar", kubeConfigPath: "fake-path.yml" }), port, {}) - kap.exit() - kap.exit() - kap.exit() - }) + const port = await getFreePort(); + const kap = new KubeAuthProxy(new Cluster({ id: "foobar", kubeConfigPath: "fake-path.yml" }), port, {}); + kap.exit(); + kap.exit(); + kap.exit(); + }); describe("spawn tests", () => { - let port: number - let mockedCP: MockProxy - let listeners: Record void> - let proxy: KubeAuthProxy + let port: number; + let mockedCP: MockProxy; + let listeners: Record void>; + let proxy: KubeAuthProxy; beforeEach(async () => { - port = await getFreePort() - mockedCP = mock() - listeners = {} + port = await getFreePort(); + mockedCP = mock(); + listeners = {}; - jest.spyOn(Kubectl.prototype, "checkBinary").mockReturnValueOnce(Promise.resolve(true)) - jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValueOnce(Promise.resolve(false)) + jest.spyOn(Kubectl.prototype, "checkBinary").mockReturnValueOnce(Promise.resolve(true)); + jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValueOnce(Promise.resolve(false)); mockedCP.on.mockImplementation((event: string, listener: (message: any, sendHandle: any) => void): ChildProcess => { - listeners[event] = listener - return mockedCP - }) - mockedCP.stderr = mock() + listeners[event] = listener; + return mockedCP; + }); + mockedCP.stderr = mock(); mockedCP.stderr.on.mockImplementation((event: string, listener: (message: any, sendHandle: any) => void): Readable => { - listeners[`stderr/${event}`] = listener - return mockedCP.stderr - }) - mockedCP.stdout = mock() + listeners[`stderr/${event}`] = listener; + return mockedCP.stderr; + }); + mockedCP.stdout = mock(); mockedCP.stdout.on.mockImplementation((event: string, listener: (message: any, sendHandle: any) => void): Readable => { - listeners[`stdout/${event}`] = listener - return mockedCP.stdout - }) + listeners[`stdout/${event}`] = listener; + return mockedCP.stdout; + }); mockSpawn.mockImplementationOnce((command: string, args: readonly string[], options: SpawnOptions): ChildProcess => { - expect(command).toBe(bundledKubectlPath()) - return mockedCP - }) - mockWaitUntilUsed.mockReturnValueOnce(Promise.resolve()) - const cluster = new Cluster({ id: "foobar", kubeConfigPath: "fake-path.yml" }) - jest.spyOn(cluster, "apiUrl", "get").mockReturnValue("https://fake.k8s.internal") - proxy = new KubeAuthProxy(cluster, port, {}) - }) + expect(command).toBe(bundledKubectlPath()); + return mockedCP; + }); + mockWaitUntilUsed.mockReturnValueOnce(Promise.resolve()); + const cluster = new Cluster({ id: "foobar", kubeConfigPath: "fake-path.yml" }); + jest.spyOn(cluster, "apiUrl", "get").mockReturnValue("https://fake.k8s.internal"); + proxy = new KubeAuthProxy(cluster, port, {}); + }); it("should call spawn and broadcast errors", async () => { - await proxy.run() - listeners["error"]({ message: "foobarbat" }) + await proxy.run(); + listeners["error"]({ message: "foobarbat" }); - expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "foobarbat", error: true }) - }) + expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "foobarbat", error: true }); + }); it("should call spawn and broadcast exit", async () => { - await proxy.run() - listeners["exit"](0) + await proxy.run(); + listeners["exit"](0); - expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "proxy exited with code: 0", error: false }) - }) + expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "proxy exited with code: 0", error: false }); + }); it("should call spawn and broadcast errors from stderr", async () => { - await proxy.run() - listeners["stderr/data"]("an error") + await proxy.run(); + listeners["stderr/data"]("an error"); - expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "an error", error: true }) - }) + expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "an error", error: true }); + }); it("should call spawn and broadcast stdout serving info", async () => { - await proxy.run() - listeners["stdout/data"]("Starting to serve on") + await proxy.run(); + listeners["stdout/data"]("Starting to serve on"); - expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "Authentication proxy started\n" }) - }) + expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "Authentication proxy started\n" }); + }); it("should call spawn and broadcast stdout other info", async () => { - await proxy.run() - listeners["stdout/data"]("some info") + await proxy.run(); + listeners["stdout/data"]("some info"); - expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "some info" }) - }) - }) -}) + expect(mockBroadcastIpc).toBeCalledWith("kube-auth:foobar", { data: "some info" }); + }); + }); +}); diff --git a/src/main/__test__/kubeconfig-manager.test.ts b/src/main/__test__/kubeconfig-manager.test.ts index a0a4060111..152a13055d 100644 --- a/src/main/__test__/kubeconfig-manager.test.ts +++ b/src/main/__test__/kubeconfig-manager.test.ts @@ -21,24 +21,24 @@ jest.mock("winston", () => ({ Console: jest.fn(), File: jest.fn(), } -})) +})); -import { KubeconfigManager } from "../kubeconfig-manager" -import mockFs from "mock-fs" +import { KubeconfigManager } from "../kubeconfig-manager"; +import mockFs from "mock-fs"; import { Cluster } from "../cluster"; import { workspaceStore } from "../../common/workspace-store"; import { ContextHandler } from "../context-handler"; import { getFreePort } from "../port"; -import fse from "fs-extra" +import fse from "fs-extra"; import { loadYaml } from "@kubernetes/client-node"; import { Console } from "console"; -console = new Console(process.stdout, process.stderr) // fix mockFS +console = new Console(process.stdout, process.stderr); // fix mockFS describe("kubeconfig manager tests", () => { beforeEach(() => { - jest.clearAllMocks() - }) + jest.clearAllMocks(); + }); beforeEach(() => { const mockOpts = { @@ -63,13 +63,13 @@ describe("kubeconfig manager tests", () => { kind: "Config", preferences: {}, }) - } - mockFs(mockOpts) - }) + }; + mockFs(mockOpts); + }); afterEach(() => { - mockFs.restore() - }) + mockFs.restore(); + }); it("should create 'temp' kube config with proxy", async () => { const cluster = new Cluster({ @@ -77,19 +77,19 @@ describe("kubeconfig manager tests", () => { contextName: "minikube", kubeConfigPath: "minikube-config.yml", workspace: workspaceStore.currentWorkspaceId - }) - const contextHandler = new ContextHandler(cluster) - const port = await getFreePort() - const kubeConfManager = await KubeconfigManager.create(cluster, contextHandler, port) + }); + const contextHandler = new ContextHandler(cluster); + const port = await getFreePort(); + const kubeConfManager = await KubeconfigManager.create(cluster, contextHandler, port); - expect(logger.error).not.toBeCalled() - expect(kubeConfManager.getPath()).toBe("tmp/kubeconfig-foo") - const file = await fse.readFile(kubeConfManager.getPath()) - const yml = loadYaml(file.toString()) - expect(yml["current-context"]).toBe("minikube") - expect(yml["clusters"][0]["cluster"]["server"]).toBe(`http://127.0.0.1:${port}/foo`) - expect(yml["users"][0]["name"]).toBe("proxy") - }) + expect(logger.error).not.toBeCalled(); + expect(kubeConfManager.getPath()).toBe("tmp/kubeconfig-foo"); + const file = await fse.readFile(kubeConfManager.getPath()); + const yml = loadYaml(file.toString()); + expect(yml["current-context"]).toBe("minikube"); + expect(yml["clusters"][0]["cluster"]["server"]).toBe(`http://127.0.0.1:${port}/foo`); + expect(yml["users"][0]["name"]).toBe("proxy"); + }); it("should remove 'temp' kube config on unlink and remove reference from inside class", async () => { const cluster = new Cluster({ @@ -97,16 +97,16 @@ describe("kubeconfig manager tests", () => { contextName: "minikube", kubeConfigPath: "minikube-config.yml", workspace: workspaceStore.currentWorkspaceId - }) - const contextHandler = new ContextHandler(cluster) - const port = await getFreePort() - const kubeConfManager = await KubeconfigManager.create(cluster, contextHandler, port) + }); + const contextHandler = new ContextHandler(cluster); + const port = await getFreePort(); + const kubeConfManager = await KubeconfigManager.create(cluster, contextHandler, port); - const configPath = kubeConfManager.getPath() - expect(await fse.pathExists(configPath)).toBe(true) - await kubeConfManager.unlink() - expect(await fse.pathExists(configPath)).toBe(false) - await kubeConfManager.unlink() // doesn't throw - expect(kubeConfManager.getPath()).toBeUndefined() - }) -}) + const configPath = kubeConfManager.getPath(); + expect(await fse.pathExists(configPath)).toBe(true); + await kubeConfManager.unlink(); + expect(await fse.pathExists(configPath)).toBe(false); + await kubeConfManager.unlink(); // doesn't throw + expect(kubeConfManager.getPath()).toBeUndefined(); + }); +}); diff --git a/src/main/app-updater.ts b/src/main/app-updater.ts index 3613c3ef18..c7b6659149 100644 --- a/src/main/app-updater.ts +++ b/src/main/app-updater.ts @@ -1,19 +1,19 @@ -import { autoUpdater } from "electron-updater" -import logger from "./logger" +import { autoUpdater } from "electron-updater"; +import logger from "./logger"; export class AppUpdater { - static readonly defaultUpdateIntervalMs = 1000 * 60 * 60 * 24 // once a day + static readonly defaultUpdateIntervalMs = 1000 * 60 * 60 * 24; // once a day static checkForUpdates() { - return autoUpdater.checkForUpdatesAndNotify() + return autoUpdater.checkForUpdatesAndNotify(); } constructor(protected updateInterval = AppUpdater.defaultUpdateIntervalMs) { - autoUpdater.logger = logger + autoUpdater.logger = logger; } public start() { - setInterval(AppUpdater.checkForUpdates, this.updateInterval) + setInterval(AppUpdater.checkForUpdates, this.updateInterval); return AppUpdater.checkForUpdates(); } } diff --git a/src/main/cluster-detectors/base-cluster-detector.ts b/src/main/cluster-detectors/base-cluster-detector.ts index 8663313005..f73cc2ac81 100644 --- a/src/main/cluster-detectors/base-cluster-detector.ts +++ b/src/main/cluster-detectors/base-cluster-detector.ts @@ -1,21 +1,21 @@ -import request, { RequestPromiseOptions } from "request-promise-native" +import request, { RequestPromiseOptions } from "request-promise-native"; import { Cluster } from "../cluster"; export type ClusterDetectionResult = { value: string | number | boolean accuracy: number -} +}; export class BaseClusterDetector { - cluster: Cluster - key: string + cluster: Cluster; + key: string; constructor(cluster: Cluster) { - this.cluster = cluster + this.cluster = cluster; } detect(): Promise { - return null + return null; } protected async k8sRequest(path: string, options: RequestPromiseOptions = {}): Promise { @@ -28,6 +28,6 @@ export class BaseClusterDetector { Host: `${this.cluster.id}.${new URL(this.cluster.kubeProxyUrl).host}`, // required in ClusterManager.getClusterForRequest() ...(options.headers || {}), }, - }) + }); } } \ No newline at end of file diff --git a/src/main/cluster-detectors/cluster-id-detector.ts b/src/main/cluster-detectors/cluster-id-detector.ts index 558e52d43c..8419ae9db4 100644 --- a/src/main/cluster-detectors/cluster-id-detector.ts +++ b/src/main/cluster-detectors/cluster-id-detector.ts @@ -1,23 +1,23 @@ import { BaseClusterDetector } from "./base-cluster-detector"; -import { createHash } from "crypto" +import { createHash } from "crypto"; import { ClusterMetadataKey } from "../cluster"; export class ClusterIdDetector extends BaseClusterDetector { - key = ClusterMetadataKey.CLUSTER_ID + key = ClusterMetadataKey.CLUSTER_ID; public async detect() { - let id: string + let id: string; try { - id = await this.getDefaultNamespaceId() + id = await this.getDefaultNamespaceId(); } catch(_) { - id = this.cluster.apiUrl + id = this.cluster.apiUrl; } - const value = createHash("sha256").update(id).digest("hex") - return { value: value, accuracy: 100 } + const value = createHash("sha256").update(id).digest("hex"); + return { value: value, accuracy: 100 }; } protected async getDefaultNamespaceId() { - const response = await this.k8sRequest("/api/v1/namespaces/default") - return response.metadata.uid + const response = await this.k8sRequest("/api/v1/namespaces/default"); + return response.metadata.uid; } } \ No newline at end of file diff --git a/src/main/cluster-detectors/detector-registry.ts b/src/main/cluster-detectors/detector-registry.ts index 577fdf2d85..d4abe01304 100644 --- a/src/main/cluster-detectors/detector-registry.ts +++ b/src/main/cluster-detectors/detector-registry.ts @@ -12,34 +12,34 @@ export class DetectorRegistry { registry = observable.array([], { deep: false }); add(detectorClass: typeof BaseClusterDetector) { - this.registry.push(detectorClass) + this.registry.push(detectorClass); } async detectForCluster(cluster: Cluster): Promise { - const results: {[key: string]: ClusterDetectionResult } = {} + const results: {[key: string]: ClusterDetectionResult } = {}; for (const detectorClass of this.registry) { - const detector = new detectorClass(cluster) + const detector = new detectorClass(cluster); try { - const data = await detector.detect() + const data = await detector.detect(); if (!data) continue; - const existingValue = results[detector.key] + const existingValue = results[detector.key]; if (existingValue && existingValue.accuracy > data.accuracy) continue; // previous value exists and is more accurate - results[detector.key] = data + results[detector.key] = data; } catch (e) { // detector raised error, do nothing } } - const metadata: ClusterMetadata = {} + const metadata: ClusterMetadata = {}; for (const [key, result] of Object.entries(results)) { - metadata[key] = result.value + metadata[key] = result.value; } - return metadata + return metadata; } } -export const detectorRegistry = new DetectorRegistry() -detectorRegistry.add(ClusterIdDetector) -detectorRegistry.add(LastSeenDetector) -detectorRegistry.add(VersionDetector) -detectorRegistry.add(DistributionDetector) -detectorRegistry.add(NodesCountDetector) \ No newline at end of file +export const detectorRegistry = new DetectorRegistry(); +detectorRegistry.add(ClusterIdDetector); +detectorRegistry.add(LastSeenDetector); +detectorRegistry.add(VersionDetector); +detectorRegistry.add(DistributionDetector); +detectorRegistry.add(NodesCountDetector); \ No newline at end of file diff --git a/src/main/cluster-detectors/distribution-detector.ts b/src/main/cluster-detectors/distribution-detector.ts index b5895f8a71..181425cb26 100644 --- a/src/main/cluster-detectors/distribution-detector.ts +++ b/src/main/cluster-detectors/distribution-detector.ts @@ -2,79 +2,79 @@ import { BaseClusterDetector } from "./base-cluster-detector"; import { ClusterMetadataKey } from "../cluster"; export class DistributionDetector extends BaseClusterDetector { - key = ClusterMetadataKey.DISTRIBUTION - version: string + key = ClusterMetadataKey.DISTRIBUTION; + version: string; public async detect() { - this.version = await this.getKubernetesVersion() + this.version = await this.getKubernetesVersion(); if (await this.isRancher()) { - return { value: "rancher", accuracy: 80} + return { value: "rancher", accuracy: 80}; } if (this.isGKE()) { - return { value: "gke", accuracy: 80} + return { value: "gke", accuracy: 80}; } if (this.isEKS()) { - return { value: "eks", accuracy: 80} + return { value: "eks", accuracy: 80}; } if (this.isIKS()) { - return { value: "iks", accuracy: 80} + return { value: "iks", accuracy: 80}; } if (this.isAKS()) { - return { value: "aks", accuracy: 80} + return { value: "aks", accuracy: 80}; } if (this.isDigitalOcean()) { - return { value: "digitalocean", accuracy: 90} + return { value: "digitalocean", accuracy: 90}; } if (this.isMinikube()) { - return { value: "minikube", accuracy: 80} + return { value: "minikube", accuracy: 80}; } if (this.isCustom()) { - return { value: "custom", accuracy: 10} + return { value: "custom", accuracy: 10}; } - return { value: "unknown", accuracy: 10} + return { value: "unknown", accuracy: 10}; } public async getKubernetesVersion() { - if (this.cluster.version) return this.cluster.version + if (this.cluster.version) return this.cluster.version; - const response = await this.k8sRequest("/version") - return response.gitVersion + const response = await this.k8sRequest("/version"); + return response.gitVersion; } protected isGKE() { - return this.version.includes("gke") + return this.version.includes("gke"); } protected isEKS() { - return this.version.includes("eks") + return this.version.includes("eks"); } protected isIKS() { - return this.version.includes("IKS") + return this.version.includes("IKS"); } protected isAKS() { - return this.cluster.apiUrl.endsWith("azmk8s.io") + return this.cluster.apiUrl.endsWith("azmk8s.io"); } protected isDigitalOcean() { - return this.cluster.apiUrl.endsWith("k8s.ondigitalocean.com") + return this.cluster.apiUrl.endsWith("k8s.ondigitalocean.com"); } protected isMinikube() { - return this.cluster.contextName.startsWith("minikube") + return this.cluster.contextName.startsWith("minikube"); } protected isCustom() { - return this.version.includes("+") + return this.version.includes("+"); } protected async isRancher() { try { - const response = await this.k8sRequest("") - return response.data.find((api: any) => api?.apiVersion?.group === "meta.cattle.io") !== undefined + const response = await this.k8sRequest(""); + return response.data.find((api: any) => api?.apiVersion?.group === "meta.cattle.io") !== undefined; } catch (e) { - return false + return false; } } } \ No newline at end of file diff --git a/src/main/cluster-detectors/last-seen-detector.ts b/src/main/cluster-detectors/last-seen-detector.ts index 0c231116fe..d56483625a 100644 --- a/src/main/cluster-detectors/last-seen-detector.ts +++ b/src/main/cluster-detectors/last-seen-detector.ts @@ -2,12 +2,12 @@ import { BaseClusterDetector } from "./base-cluster-detector"; import { ClusterMetadataKey } from "../cluster"; export class LastSeenDetector extends BaseClusterDetector { - key = ClusterMetadataKey.LAST_SEEN + key = ClusterMetadataKey.LAST_SEEN; public async detect() { if (!this.cluster.accessible) return null; - await this.k8sRequest("/version") - return { value: new Date().toJSON(), accuracy: 100 } + await this.k8sRequest("/version"); + return { value: new Date().toJSON(), accuracy: 100 }; } } \ No newline at end of file diff --git a/src/main/cluster-detectors/nodes-count-detector.ts b/src/main/cluster-detectors/nodes-count-detector.ts index 858ff43d9f..ba5fc93583 100644 --- a/src/main/cluster-detectors/nodes-count-detector.ts +++ b/src/main/cluster-detectors/nodes-count-detector.ts @@ -2,16 +2,16 @@ import { BaseClusterDetector } from "./base-cluster-detector"; import { ClusterMetadataKey } from "../cluster"; export class NodesCountDetector extends BaseClusterDetector { - key = ClusterMetadataKey.NODES_COUNT + key = ClusterMetadataKey.NODES_COUNT; public async detect() { if (!this.cluster.accessible) return null; - const nodeCount = await this.getNodeCount() - return { value: nodeCount, accuracy: 100} + const nodeCount = await this.getNodeCount(); + return { value: nodeCount, accuracy: 100}; } protected async getNodeCount(): Promise { - const response = await this.k8sRequest("/api/v1/nodes") - return response.items.length + const response = await this.k8sRequest("/api/v1/nodes"); + return response.items.length; } } \ No newline at end of file diff --git a/src/main/cluster-detectors/version-detector.ts b/src/main/cluster-detectors/version-detector.ts index 4092b40b42..e59e6291b9 100644 --- a/src/main/cluster-detectors/version-detector.ts +++ b/src/main/cluster-detectors/version-detector.ts @@ -2,16 +2,16 @@ import { BaseClusterDetector } from "./base-cluster-detector"; import { ClusterMetadataKey } from "../cluster"; export class VersionDetector extends BaseClusterDetector { - key = ClusterMetadataKey.VERSION - value: string + key = ClusterMetadataKey.VERSION; + value: string; public async detect() { - const version = await this.getKubernetesVersion() - return { value: version, accuracy: 100} + const version = await this.getKubernetesVersion(); + return { value: version, accuracy: 100}; } public async getKubernetesVersion() { - const response = await this.k8sRequest("/version") - return response.gitVersion + const response = await this.k8sRequest("/version"); + return response.gitVersion; } } \ No newline at end of file diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index 1a479e724e..9b2e88ef89 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -1,16 +1,16 @@ import "../common/cluster-ipc"; -import type http from "http" -import { ipcMain } from "electron" +import type http from "http"; +import { ipcMain } from "electron"; import { autorun } from "mobx"; -import { clusterStore, getClusterIdFromHost } from "../common/cluster-store" -import { Cluster } from "./cluster" +import { clusterStore, getClusterIdFromHost } from "../common/cluster-store"; +import { Cluster } from "./cluster"; import logger from "./logger"; import { apiKubePrefix } from "../common/vars"; import { Singleton } from "../common/utils"; export class ClusterManager extends Singleton { constructor(public readonly port: number) { - super() + super(); // auto-init clusters autorun(() => { clusterStore.enabledClustersList.forEach(cluster => { @@ -34,52 +34,52 @@ export class ClusterManager extends Singleton { delay: 250 }); - ipcMain.on("network:offline", () => { this.onNetworkOffline() }) - ipcMain.on("network:online", () => { this.onNetworkOnline() }) + ipcMain.on("network:offline", () => { this.onNetworkOffline(); }); + ipcMain.on("network:online", () => { this.onNetworkOnline(); }); } protected onNetworkOffline() { - logger.info("[CLUSTER-MANAGER]: network is offline") + logger.info("[CLUSTER-MANAGER]: network is offline"); clusterStore.enabledClustersList.forEach((cluster) => { if (!cluster.disconnected) { - cluster.online = false - cluster.accessible = false - cluster.refreshConnectionStatus().catch((e) => e) + cluster.online = false; + cluster.accessible = false; + cluster.refreshConnectionStatus().catch((e) => e); } - }) + }); } protected onNetworkOnline() { - logger.info("[CLUSTER-MANAGER]: network is online") + logger.info("[CLUSTER-MANAGER]: network is online"); clusterStore.enabledClustersList.forEach((cluster) => { if (!cluster.disconnected) { - cluster.refreshConnectionStatus().catch((e) => e) + cluster.refreshConnectionStatus().catch((e) => e); } - }) + }); } stop() { clusterStore.clusters.forEach((cluster: Cluster) => { cluster.disconnect(); - }) + }); } getClusterForRequest(req: http.IncomingMessage): Cluster { - let cluster: Cluster = null + let cluster: Cluster = null; // lens-server is connecting to 127.0.0.1:/ if (req.headers.host.startsWith("127.0.0.1")) { - const clusterId = req.url.split("/")[1] - cluster = clusterStore.getById(clusterId) + const clusterId = req.url.split("/")[1]; + cluster = clusterStore.getById(clusterId); if (cluster) { // we need to swap path prefix so that request is proxied to kube api - req.url = req.url.replace(`/${clusterId}`, apiKubePrefix) + req.url = req.url.replace(`/${clusterId}`, apiKubePrefix); } } else if (req.headers["x-cluster-id"]) { - cluster = clusterStore.getById(req.headers["x-cluster-id"].toString()) + cluster = clusterStore.getById(req.headers["x-cluster-id"].toString()); } else { const clusterId = getClusterIdFromHost(req.headers.host); - cluster = clusterStore.getById(clusterId) + cluster = clusterStore.getById(clusterId); } return cluster; diff --git a/src/main/cluster.ts b/src/main/cluster.ts index a2b71a865b..e2831e8c3f 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -1,18 +1,18 @@ -import { ipcMain } from "electron" -import type { ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences } from "../common/cluster-store" +import { ipcMain } from "electron"; +import type { ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences } from "../common/cluster-store"; import type { IMetricsReqParams } from "../renderer/api/endpoints/metrics.api"; import type { WorkspaceId } from "../common/workspace-store"; import { action, computed, observable, reaction, toJS, when } from "mobx"; import { apiKubePrefix } from "../common/vars"; import { broadcastMessage } from "../common/ipc"; -import { ContextHandler } from "./context-handler" -import { AuthorizationV1Api, CoreV1Api, KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node" +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 request, { RequestPromiseOptions } from "request-promise-native" +import { KubeconfigManager } from "./kubeconfig-manager"; +import { getNodeWarningConditions, loadConfig, podHasIssues } from "../common/kube-helpers"; +import request, { RequestPromiseOptions } from "request-promise-native"; import { apiResources } from "../common/rbac"; -import logger from "./logger" +import logger from "./logger"; import { VersionDetector } from "./cluster-detectors/version-detector"; import { detectorRegistry } from "./cluster-detectors/detector-registry"; @@ -32,7 +32,7 @@ export enum ClusterMetadataKey { export type ClusterRefreshOptions = { refreshMetadata?: boolean -} +}; export interface ClusterState { initialized: boolean; @@ -50,7 +50,7 @@ export interface ClusterState { export class Cluster implements ClusterModel, ClusterState { public id: ClusterId; - public kubeCtl: Kubectl + public kubeCtl: Kubectl; public contextHandler: ContextHandler; public ownerRef: string; protected kubeconfigManager: KubeconfigManager; @@ -86,23 +86,23 @@ export class Cluster implements ClusterModel, ClusterState { } @computed get name() { - return this.preferences.clusterName || this.contextName + return this.preferences.clusterName || this.contextName; } get version(): string { - return String(this.metadata?.version) || "" + return String(this.metadata?.version) || ""; } constructor(model: ClusterModel) { this.updateModel(model); - const kubeconfig = this.getKubeconfig() + const kubeconfig = this.getKubeconfig(); if (kubeconfig.getContextObject(this.contextName)) { - this.apiUrl = kubeconfig.getCluster(kubeconfig.getContextObject(this.contextName).cluster).server + this.apiUrl = kubeconfig.getCluster(kubeconfig.getContextObject(this.contextName).cluster).server; } } get isManaged(): boolean { - return !!this.ownerRef + return !!this.ownerRef; } @action @@ -131,16 +131,16 @@ export class Cluster implements ClusterModel, ClusterState { } protected bindEvents() { - logger.info(`[CLUSTER]: bind events`, this.getMeta()) - const refreshTimer = setInterval(() => !this.disconnected && this.refresh(), 30000) // every 30s - const refreshMetadataTimer = setInterval(() => !this.disconnected && this.refreshMetadata(), 900000) // every 15 minutes + logger.info(`[CLUSTER]: bind events`, this.getMeta()); + const refreshTimer = setInterval(() => !this.disconnected && this.refresh(), 30000); // every 30s + const refreshMetadataTimer = setInterval(() => !this.disconnected && this.refreshMetadata(), 900000); // every 15 minutes if (ipcMain) { this.eventDisposers.push( reaction(() => this.getState(), () => this.pushState()), () => { - clearInterval(refreshTimer) - clearInterval(refreshMetadataTimer) + clearInterval(refreshTimer); + clearInterval(refreshMetadataTimer); }, ); } @@ -165,20 +165,20 @@ export class Cluster implements ClusterModel, ClusterState { if (this.disconnected || !this.accessible) { await this.reconnect(); } - await this.refreshConnectionStatus() + await this.refreshConnectionStatus(); if (this.accessible) { - await this.refreshAllowedResources() - this.isAdmin = await this.isClusterAdmin() - this.ready = true - this.ensureKubectl() + await this.refreshAllowedResources(); + this.isAdmin = await this.isClusterAdmin(); + this.ready = true; + this.ensureKubectl(); } - this.activated = true + this.activated = true; return this.pushState(); } protected async ensureKubectl() { - this.kubeCtl = new Kubectl(this.version) - return this.kubeCtl.ensureKubectl() // download kubectl in background, so it's not blocking dashboard + this.kubeCtl = new Kubectl(this.version); + return this.kubeCtl.ensureKubectl(); // download kubectl in background, so it's not blocking dashboard } @action @@ -214,9 +214,9 @@ export class Cluster implements ClusterModel, ClusterState { this.refreshAllowedResources(), ]); if (opts.refreshMetadata) { - this.refreshMetadata() + this.refreshMetadata(); } - this.ready = true + this.ready = true; } this.pushState(); } @@ -224,9 +224,9 @@ export class Cluster implements ClusterModel, ClusterState { @action async refreshMetadata() { logger.info(`[CLUSTER]: refreshMetadata`, this.getMeta()); - const metadata = await detectorRegistry.detectForCluster(this) - const existingMetadata = this.metadata - this.metadata = Object.assign(existingMetadata, metadata) + const metadata = await detectorRegistry.detectForCluster(this); + const existingMetadata = this.metadata; + this.metadata = Object.assign(existingMetadata, metadata); } @action @@ -256,16 +256,16 @@ export class Cluster implements ClusterModel, ClusterState { } getProxyKubeconfigPath(): string { - return this.kubeconfigManager.getPath() + return this.kubeconfigManager.getPath(); } protected async k8sRequest(path: string, options: RequestPromiseOptions = {}): Promise { - options.headers ??= {} - options.json ??= true - options.timeout ??= 30000 - options.headers.Host = `${this.id}.${new URL(this.kubeProxyUrl).host}` // required in ClusterManager.getClusterForRequest() + options.headers ??= {}; + options.json ??= true; + options.timeout ??= 30000; + options.headers.Host = `${this.id}.${new URL(this.kubeProxyUrl).host}`; // required in ClusterManager.getClusterForRequest() - return request(this.kubeProxyUrl + path, options) + return request(this.kubeProxyUrl + path, options); } getMetrics(prometheusPath: string, queryParams: IMetricsReqParams & { query: string }) { @@ -276,17 +276,17 @@ export class Cluster implements ClusterModel, ClusterState { resolveWithFullResponse: false, json: true, qs: queryParams, - }) + }); } protected async getConnectionStatus(): Promise { try { - const versionDetector = new VersionDetector(this) - const versionData = await versionDetector.detect() - this.metadata.version = versionData.value + const versionDetector = new VersionDetector(this); + const versionData = await versionDetector.detect(); + this.metadata.version = versionData.value; return ClusterStatus.AccessGranted; } catch (error) { - logger.error(`Failed to connect cluster "${this.contextName}": ${error}`) + logger.error(`Failed to connect cluster "${this.contextName}": ${error}`); if (error.statusCode) { if (error.statusCode >= 400 && error.statusCode < 500) { this.failureReason = "Invalid credentials"; @@ -310,17 +310,17 @@ export class Cluster implements ClusterModel, ClusterState { } async canI(resourceAttributes: V1ResourceAttributes): Promise { - const authApi = this.getProxyKubeconfig().makeApiClient(AuthorizationV1Api) + const authApi = this.getProxyKubeconfig().makeApiClient(AuthorizationV1Api); try { const accessReview = await authApi.createSelfSubjectAccessReview({ apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", spec: { resourceAttributes } - }) - return accessReview.body.status.allowed + }); + return accessReview.body.status.allowed; } catch (error) { - logger.error(`failed to request selfSubjectAccessReview: ${error}`) - return false + logger.error(`failed to request selfSubjectAccessReview: ${error}`); + return false; } } @@ -329,7 +329,7 @@ export class Cluster implements ClusterModel, ClusterState { namespace: "kube-system", resource: "*", verb: "create", - }) + }); } protected async getEventCount(): Promise { @@ -345,7 +345,7 @@ export class Cluster implements ClusterModel, ClusterState { if (w.involvedObject.kind === 'Pod') { try { const { body: pod } = await client.readNamespacedPod(w.involvedObject.name, w.involvedObject.namespace); - logger.debug(`checking pod ${w.involvedObject.namespace}/${w.involvedObject.name}`) + logger.debug(`checking pod ${w.involvedObject.namespace}/${w.involvedObject.name}`); if (podHasIssues(pod)) { uniqEventSources.add(w.involvedObject.uid); } @@ -361,7 +361,7 @@ export class Cluster implements ClusterModel, ClusterState { .reduce((sum, conditions) => sum + conditions.length, 0); return uniqEventSources.size + nodeNotificationCount; } catch (error) { - logger.error("Failed to fetch event count: " + JSON.stringify(error)) + logger.error("Failed to fetch event count: " + JSON.stringify(error)); return 0; } } @@ -379,7 +379,7 @@ export class Cluster implements ClusterModel, ClusterState { }; return toJS(model, { recurseEverything: true - }) + }); } // serializable cluster-state used for sync btw main <-> renderer @@ -399,17 +399,17 @@ export class Cluster implements ClusterModel, ClusterState { }; return toJS(state, { recurseEverything: true - }) + }); } @action setState(state: ClusterState) { - Object.assign(this, state) + Object.assign(this, state); } pushState(state = this.getState()) { logger.silly(`[CLUSTER]: push-state`, state); - broadcastMessage("cluster:state", this.id, state) + broadcastMessage("cluster:state", this.id, state); } // get cluster system meta, e.g. use in "logger" @@ -422,30 +422,30 @@ export class Cluster implements ClusterModel, ClusterState { online: this.online, accessible: this.accessible, disconnected: this.disconnected, - } + }; } protected async getAllowedNamespaces() { if (this.accessibleNamespaces.length) { - return this.accessibleNamespaces + return this.accessibleNamespaces; } - const api = this.getProxyKubeconfig().makeApiClient(CoreV1Api) + const api = this.getProxyKubeconfig().makeApiClient(CoreV1Api); try { - const namespaceList = await api.listNamespace() + const namespaceList = await api.listNamespace(); const nsAccessStatuses = await Promise.all( namespaceList.body.items.map(ns => this.canI({ namespace: ns.metadata.name, resource: "pods", verb: "list", })) - ) + ); return namespaceList.body.items .filter((ns, i) => nsAccessStatuses[i]) - .map(ns => ns.metadata.name) + .map(ns => ns.metadata.name); } catch (error) { - const ctx = this.getProxyKubeconfig().getContextObject(this.contextName) - if (ctx.namespace) return [ctx.namespace] + const ctx = this.getProxyKubeconfig().getContextObject(this.contextName); + if (ctx.namespace) return [ctx.namespace]; return []; } } @@ -462,12 +462,12 @@ export class Cluster implements ClusterModel, ClusterState { verb: "list", namespace: this.allowedNamespaces[0] })) - ) + ); return apiResources .filter((resource, i) => resourceAccessStatuses[i]) - .map(apiResource => apiResource.resource) + .map(apiResource => apiResource.resource); } catch (error) { - return [] + return []; } } } diff --git a/src/main/context-handler.ts b/src/main/context-handler.ts index a3cf6185dd..10f84ced6d 100644 --- a/src/main/context-handler.ts +++ b/src/main/context-handler.ts @@ -1,21 +1,21 @@ -import type { PrometheusProvider, PrometheusService } from "./prometheus/provider-registry" +import type { PrometheusProvider, PrometheusService } from "./prometheus/provider-registry"; import type { ClusterPreferences } from "../common/cluster-store"; -import type { Cluster } from "./cluster" -import type httpProxy from "http-proxy" +import type { Cluster } from "./cluster"; +import type httpProxy from "http-proxy"; import url, { UrlWithStringQuery } from "url"; -import { CoreV1Api } from "@kubernetes/client-node" -import { prometheusProviders } from "../common/prometheus-providers" -import logger from "./logger" -import { getFreePort } from "./port" -import { KubeAuthProxy } from "./kube-auth-proxy" +import { CoreV1Api } from "@kubernetes/client-node"; +import { prometheusProviders } from "../common/prometheus-providers"; +import logger from "./logger"; +import { getFreePort } from "./port"; +import { KubeAuthProxy } from "./kube-auth-proxy"; export class ContextHandler { public proxyPort: number; public clusterUrl: UrlWithStringQuery; - protected kubeAuthProxy: KubeAuthProxy - protected apiTarget: httpProxy.ServerOptions - protected prometheusProvider: string - protected prometheusPath: string + protected kubeAuthProxy: KubeAuthProxy; + protected apiTarget: httpProxy.ServerOptions; + protected prometheusProvider: string; + protected prometheusPath: string; constructor(protected cluster: Cluster) { this.clusterUrl = url.parse(cluster.apiUrl); @@ -26,64 +26,64 @@ export class ContextHandler { this.prometheusProvider = preferences.prometheusProvider?.type; this.prometheusPath = null; if (preferences.prometheus) { - const { namespace, service, port } = preferences.prometheus - this.prometheusPath = `${namespace}/services/${service}:${port}` + const { namespace, service, port } = preferences.prometheus; + this.prometheusPath = `${namespace}/services/${service}:${port}`; } } protected async resolvePrometheusPath(): Promise { - const { service, namespace, port } = await this.getPrometheusService() - return `${namespace}/services/${service}:${port}` + const { service, namespace, port } = await this.getPrometheusService(); + return `${namespace}/services/${service}:${port}`; } async getPrometheusProvider() { if (!this.prometheusProvider) { - const service = await this.getPrometheusService() - logger.info(`using ${service.id} as prometheus provider`) - this.prometheusProvider = service.id + const service = await this.getPrometheusService(); + logger.info(`using ${service.id} as prometheus provider`); + this.prometheusProvider = service.id; } - return prometheusProviders.find(p => p.id === this.prometheusProvider) + return prometheusProviders.find(p => p.id === this.prometheusProvider); } async getPrometheusService(): Promise { const providers = this.prometheusProvider ? prometheusProviders.filter(provider => provider.id == this.prometheusProvider) : prometheusProviders; const prometheusPromises: Promise[] = providers.map(async (provider: PrometheusProvider): Promise => { - const apiClient = this.cluster.getProxyKubeconfig().makeApiClient(CoreV1Api) - return await provider.getPrometheusService(apiClient) - }) - const resolvedPrometheusServices = await Promise.all(prometheusPromises) + const apiClient = this.cluster.getProxyKubeconfig().makeApiClient(CoreV1Api); + return await provider.getPrometheusService(apiClient); + }); + const resolvedPrometheusServices = await Promise.all(prometheusPromises); const service = resolvedPrometheusServices.filter(n => n)[0]; return service || { id: "lens", namespace: "lens-metrics", service: "prometheus", port: 80 - } + }; } async getPrometheusPath(): Promise { if (!this.prometheusPath) { - this.prometheusPath = await this.resolvePrometheusPath() + this.prometheusPath = await this.resolvePrometheusPath(); } return this.prometheusPath; } async resolveAuthProxyUrl() { const proxyPort = await this.ensurePort(); - const path = this.clusterUrl.path !== "/" ? this.clusterUrl.path : "" + const path = this.clusterUrl.path !== "/" ? this.clusterUrl.path : ""; return `http://127.0.0.1:${proxyPort}${path}`; } async getApiTarget(isWatchRequest = false): Promise { if (this.apiTarget && !isWatchRequest) { - return this.apiTarget + return this.apiTarget; } - const timeout = isWatchRequest ? 4 * 60 * 60 * 1000 : 30000 // 4 hours for watch request, 30 seconds for the rest - const apiTarget = await this.newApiTarget(timeout) + const timeout = isWatchRequest ? 4 * 60 * 60 * 1000 : 30000; // 4 hours for watch request, 30 seconds for the rest + const apiTarget = await this.newApiTarget(timeout); if (!isWatchRequest) { - this.apiTarget = apiTarget + this.apiTarget = apiTarget; } - return apiTarget + return apiTarget; } protected async newApiTarget(timeout: number): Promise { @@ -95,36 +95,36 @@ export class ContextHandler { headers: { "Host": this.clusterUrl.hostname, }, - } + }; } async ensurePort(): Promise { if (!this.proxyPort) { this.proxyPort = await getFreePort(); } - return this.proxyPort + return this.proxyPort; } async ensureServer() { if (!this.kubeAuthProxy) { await this.ensurePort(); - const proxyEnv = Object.assign({}, process.env) + const proxyEnv = Object.assign({}, process.env); if (this.cluster.preferences.httpsProxy) { - proxyEnv.HTTPS_PROXY = this.cluster.preferences.httpsProxy + proxyEnv.HTTPS_PROXY = this.cluster.preferences.httpsProxy; } - this.kubeAuthProxy = new KubeAuthProxy(this.cluster, this.proxyPort, proxyEnv) - await this.kubeAuthProxy.run() + this.kubeAuthProxy = new KubeAuthProxy(this.cluster, this.proxyPort, proxyEnv); + await this.kubeAuthProxy.run(); } } stopServer() { if (this.kubeAuthProxy) { - this.kubeAuthProxy.exit() - this.kubeAuthProxy = null + this.kubeAuthProxy.exit(); + this.kubeAuthProxy = null; } } get proxyLastError(): string { - return this.kubeAuthProxy?.lastError || "" + return this.kubeAuthProxy?.lastError || ""; } } diff --git a/src/main/exit-app.ts b/src/main/exit-app.ts index bf73e022f3..b58a6e4dfc 100644 --- a/src/main/exit-app.ts +++ b/src/main/exit-app.ts @@ -6,13 +6,13 @@ import logger from "./logger"; export function exitApp() { - const windowManager = WindowManager.getInstance() - const clusterManager = ClusterManager.getInstance() - appEventBus.emit({ name: "service", action: "close" }) + const windowManager = WindowManager.getInstance(); + const clusterManager = ClusterManager.getInstance(); + appEventBus.emit({ name: "service", action: "close" }); windowManager.hide(); clusterManager.stop(); logger.info('SERVICE:QUIT'); setTimeout(() => { - app.exit() - }, 1000) + app.exit(); + }, 1000); } \ No newline at end of file diff --git a/src/main/helm/helm-chart-manager.ts b/src/main/helm/helm-chart-manager.ts index e42f7a1aaf..42c1a30ed2 100644 --- a/src/main/helm/helm-chart-manager.ts +++ b/src/main/helm/helm-chart-manager.ts @@ -1,74 +1,74 @@ import fs from "fs"; import * as yaml from "js-yaml"; -import { HelmRepo, HelmRepoManager } from "./helm-repo-manager" +import { HelmRepo, HelmRepoManager } from "./helm-repo-manager"; import logger from "../logger"; -import { promiseExec } from "../promise-exec" -import { helmCli } from "./helm-cli" +import { promiseExec } from "../promise-exec"; +import { helmCli } from "./helm-cli"; type CachedYaml = { entries: any; // todo: types -} +}; export class HelmChartManager { - protected cache: any = {} - protected repo: HelmRepo + protected cache: any = {}; + protected repo: HelmRepo; constructor(repo: HelmRepo){ - this.cache = HelmRepoManager.cache - this.repo = repo + this.cache = HelmRepoManager.cache; + this.repo = repo; } public async chart(name: string) { - const charts = await this.charts() - return charts[name] + const charts = await this.charts(); + return charts[name]; } public async charts(): Promise { try { - const cachedYaml = await this.cachedYaml() - return cachedYaml["entries"] + const cachedYaml = await this.cachedYaml(); + return cachedYaml["entries"]; } catch(error) { - logger.error(error) - return [] + logger.error(error); + return []; } } public async getReadme(name: string, version = "") { - const helm = await helmCli.binaryPath() + 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)}) - return stdout + const { stdout, stderr} = 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)}) - return stdout + const { stdout, stderr} = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);}); + return stdout; } } public async getValues(name: string, version = "") { - const helm = await helmCli.binaryPath() + 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, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);}); - return stdout + return stdout; } else { - const { stdout, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr)}) + const { stdout, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);}); - return stdout + return stdout; } } protected async cachedYaml(): Promise { if (!(this.repo.name in this.cache)) { - const cacheFile = await fs.promises.readFile(this.repo.cacheFilePath, 'utf-8') - const data = yaml.safeLoad(cacheFile) + 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)) + this.cache[this.repo.name] = Buffer.from(JSON.stringify(data)); } - return JSON.parse(this.cache[this.repo.name].toString()) + return JSON.parse(this.cache[this.repo.name].toString()); } } diff --git a/src/main/helm/helm-cli.ts b/src/main/helm/helm-cli.ts index 1484ceacf1..34a3becc33 100644 --- a/src/main/helm/helm-cli.ts +++ b/src/main/helm/helm-cli.ts @@ -1,6 +1,6 @@ -import packageInfo from "../../../package.json" -import path from "path" -import { LensBinary, LensBinaryOpts } from "../lens-binary" +import packageInfo from "../../../package.json"; +import path from "path"; +import { LensBinary, LensBinaryOpts } from "../lens-binary"; import { isProduction } from "../../common/vars"; export class HelmCli extends LensBinary { @@ -11,24 +11,24 @@ export class HelmCli extends LensBinary { baseDir: baseDir, originalBinaryName: "helm", newBinaryName: "helm3" - } - super(opts) + }; + super(opts); } protected getTarName(): string | null { - return `${this.binaryName}-v${this.binaryVersion}-${this.platformName}-${this.arch}.tar.gz` + return `${this.binaryName}-v${this.binaryVersion}-${this.platformName}-${this.arch}.tar.gz`; } protected getUrl() { - return `https://get.helm.sh/helm-v${this.binaryVersion}-${this.platformName}-${this.arch}.tar.gz` + return `https://get.helm.sh/helm-v${this.binaryVersion}-${this.platformName}-${this.arch}.tar.gz`; } protected getBinaryPath() { - return path.join(this.dirname, this.binaryName) + return path.join(this.dirname, this.binaryName); } protected getOriginalBinaryPath() { - return path.join(this.dirname, this.platformName + "-" + this.arch, this.originalBinaryName) + return path.join(this.dirname, this.platformName + "-" + this.arch, this.originalBinaryName); } } diff --git a/src/main/helm/helm-release-manager.ts b/src/main/helm/helm-release-manager.ts index 80be023227..3a8b4707ba 100644 --- a/src/main/helm/helm-release-manager.ts +++ b/src/main/helm/helm-release-manager.ts @@ -1,7 +1,7 @@ import * as tempy from "tempy"; import fs from "fs"; import * as yaml from "js-yaml"; -import { promiseExec} from "../promise-exec" +import { promiseExec} from "../promise-exec"; import { helmCli } from "./helm-cli"; import { Cluster } from "../cluster"; import { toCamelCase } from "../../common/utils/camelCase"; @@ -9,103 +9,103 @@ import { toCamelCase } from "../../common/utils/camelCase"; export class HelmReleaseManager { public async listReleases(pathToKubeconfig: string, namespace?: string) { - const helm = await helmCli.binaryPath() - const namespaceFlag = namespace ? `-n ${namespace}` : "--all-namespaces" - const { stdout } = await promiseExec(`"${helm}" ls --output json ${namespaceFlag} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr)}) + const helm = await helmCli.binaryPath(); + const namespaceFlag = namespace ? `-n ${namespace}` : "--all-namespaces"; + const { stdout } = await promiseExec(`"${helm}" ls --output json ${namespaceFlag} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);}); - const output = JSON.parse(stdout) + const output = JSON.parse(stdout); if (output.length == 0) { - return output + return output; } output.forEach((release: any, index: number) => { - output[index] = toCamelCase(release) + output[index] = toCamelCase(release); }); - return output + return output; } public async installChart(chart: string, values: any, name: string, namespace: string, version: string, pathToKubeconfig: string){ - const helm = await helmCli.binaryPath() - const fileName = tempy.file({name: "values.yaml"}) - await fs.promises.writeFile(fileName, yaml.safeDump(values)) + const helm = await helmCli.binaryPath(); + const fileName = tempy.file({name: "values.yaml"}); + await fs.promises.writeFile(fileName, yaml.safeDump(values)); try { - let generateName = "" + let generateName = ""; if (!name) { - generateName = "--generate-name" - name = "" + 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, 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(); return { log: stdout, release: { name: releaseName, namespace: namespace } - } + }; } finally { - await fs.promises.unlink(fileName) + await fs.promises.unlink(fileName); } } public async upgradeRelease(name: string, chart: string, values: any, namespace: string, version: string, cluster: Cluster){ - const helm = await helmCli.binaryPath() - const fileName = tempy.file({name: "values.yaml"}) - await fs.promises.writeFile(fileName, yaml.safeDump(values)) + const helm = await helmCli.binaryPath(); + const fileName = tempy.file({name: "values.yaml"}); + 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, stderr } = 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) - } + }; } finally { - await fs.promises.unlink(fileName) + await fs.promises.unlink(fileName); } } 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 release = JSON.parse(stdout) - release.resources = await this.getResources(name, namespace, cluster) - return release + 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 release = JSON.parse(stdout); + release.resources = await this.getResources(name, namespace, cluster); + return release; } 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 helm = await helmCli.binaryPath(); + const { stdout, stderr } = await promiseExec(`"${helm}" delete ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);}); - return stdout + 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)}) - return stdout + 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);}); + 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)}) - return JSON.parse(stdout) + const helm = await helmCli.binaryPath(); + const {stdout, stderr} = 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)}) - return stdout + const helm = await helmCli.binaryPath(); + const {stdout, stderr} = await promiseExec(`"${helm}" rollback ${name} ${revision} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);}); + return stdout; } protected async getResources(name: string, namespace: string, cluster: Cluster) { - const helm = await helmCli.binaryPath() - const kubectl = await cluster.kubeCtl.getPath() - const pathToKubeconfig = cluster.getProxyKubeconfigPath() + 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) => { - return { stdout: JSON.stringify({items: []})} - }) - return stdout + return { stdout: JSON.stringify({items: []})}; + }); + return stdout; } } -export const releaseManager = new HelmReleaseManager() +export const releaseManager = new HelmReleaseManager(); diff --git a/src/main/helm/helm-repo-manager.ts b/src/main/helm/helm-repo-manager.ts index c2af9ea7ba..dff372a301 100644 --- a/src/main/helm/helm-repo-manager.ts +++ b/src/main/helm/helm-repo-manager.ts @@ -10,7 +10,7 @@ import logger from "../logger"; export type HelmEnv = Record & { HELM_REPOSITORY_CACHE?: string; HELM_REPOSITORY_CONFIG?: string; -} +}; export interface HelmRepoConfig { repositories: HelmRepo[] @@ -29,11 +29,11 @@ export interface HelmRepo { } export class HelmRepoManager extends Singleton { - static cache = {} // todo: remove implicit updates in helm-chart-manager.ts + static cache = {}; // todo: remove implicit updates in helm-chart-manager.ts protected repos: HelmRepo[]; - protected helmEnv: HelmEnv - protected initialized: boolean + protected helmEnv: HelmEnv; + protected initialized: boolean; async loadAvailableRepos(): Promise { const res = await customRequestPromise({ @@ -46,34 +46,34 @@ export class HelmRepoManager extends Singleton { } async init() { - helmCli.setLogger(logger) + helmCli.setLogger(logger); await helmCli.ensureBinary(); if (!this.initialized) { - this.helmEnv = await this.parseHelmEnv() - await this.update() - this.initialized = true + this.helmEnv = await this.parseHelmEnv(); + await this.update(); + this.initialized = true; } } protected async parseHelmEnv() { - const helm = await helmCli.binaryPath() + const helm = await helmCli.binaryPath(); const { stdout } = await promiseExec(`"${helm}" env`).catch((error) => { - throw(error.stderr) - }) - const lines = stdout.split(/\r?\n/) // split by new line feed - const env: HelmEnv = {} + throw(error.stderr); + }); + const lines = stdout.split(/\r?\n/); // split by new line feed + const env: HelmEnv = {}; lines.forEach((line: string) => { - const [key, value] = line.split("=") + const [key, value] = line.split("="); if (key && value) { - env[key] = value.replace(/"/g, "") // strip quotas + env[key] = value.replace(/"/g, ""); // strip quotas } - }) - return env + }); + return env; } public async repositories(): Promise { if (!this.initialized) { - await this.init() + await this.init(); } try { const repoConfigFile = this.helmEnv.HELM_REPOSITORY_CONFIG; @@ -91,41 +91,41 @@ export class HelmRepoManager extends Singleton { cacheFilePath: `${this.helmEnv.HELM_REPOSITORY_CACHE}/${repo.name}-index.yaml` })); } catch (error) { - logger.error(`[HELM]: repositories listing error "${error}"`) - return [] + logger.error(`[HELM]: repositories listing error "${error}"`); + return []; } } public async repository(name: string) { - const repositories = await this.repositories() + const repositories = await this.repositories(); return repositories.find(repo => repo.name == name); } public async update() { - const helm = await helmCli.binaryPath() + const helm = await helmCli.binaryPath(); const { stdout } = await promiseExec(`"${helm}" repo update`).catch((error) => { - return { stdout: error.stdout } - }) - return stdout + return { stdout: error.stdout }; + }); + return stdout; } public async addRepo({ name, url }: HelmRepo) { logger.info(`[HELM]: adding repo "${name}" from ${url}`); - const helm = await helmCli.binaryPath() + const helm = await helmCli.binaryPath(); const { stdout } = await promiseExec(`"${helm}" repo add ${name} ${url}`).catch((error) => { - throw(error.stderr) - }) - return stdout + throw(error.stderr); + }); + return stdout; } public async removeRepo({ name, url }: HelmRepo): Promise { logger.info(`[HELM]: removing repo "${name}" from ${url}`); - const helm = await helmCli.binaryPath() + const helm = await helmCli.binaryPath(); const { stdout, stderr } = await promiseExec(`"${helm}" repo remove ${name}`).catch((error) => { - throw(error.stderr) - }) - return stdout + throw(error.stderr); + }); + return stdout; } } -export const repoManager = HelmRepoManager.getInstance() +export const repoManager = HelmRepoManager.getInstance(); diff --git a/src/main/helm/helm-service.ts b/src/main/helm/helm-service.ts index 664a30358c..88ca4dda3e 100644 --- a/src/main/helm/helm-service.ts +++ b/src/main/helm/helm-service.ts @@ -6,93 +6,93 @@ import { releaseManager } from "./helm-release-manager"; class HelmService { public async installChart(cluster: Cluster, data: { chart: string; values: {}; name: string; namespace: string; version: string }) { - return await releaseManager.installChart(data.chart, data.values, data.name, data.namespace, data.version, cluster.getProxyKubeconfigPath()) + return await releaseManager.installChart(data.chart, data.values, data.name, data.namespace, data.version, cluster.getProxyKubeconfigPath()); } public async listCharts() { - const charts: any = {} - await repoManager.init() - const repositories = await repoManager.repositories() + const charts: any = {}; + await repoManager.init(); + const repositories = await repoManager.repositories(); for (const repo of repositories) { - charts[repo.name] = {} - const manager = new HelmChartManager(repo) - let entries = await manager.charts() - entries = this.excludeDeprecated(entries) + charts[repo.name] = {}; + const manager = new HelmChartManager(repo); + let entries = await manager.charts(); + entries = this.excludeDeprecated(entries); for (const key in entries) { - entries[key] = entries[key][0] + entries[key] = entries[key][0]; } - charts[repo.name] = entries + charts[repo.name] = entries; } - return charts + return charts; } public async getChart(repoName: string, chartName: string, version = "") { const result = { readme: "", versions: {} - } - const repo = await repoManager.repository(repoName) - const chartManager = new HelmChartManager(repo) - const chart = await chartManager.chart(chartName) - result.readme = await chartManager.getReadme(chartName, version) - result.versions = chart - return result + }; + const repo = await repoManager.repository(repoName); + const chartManager = new HelmChartManager(repo); + const chart = await chartManager.chart(chartName); + result.readme = await chartManager.getReadme(chartName, version); + result.versions = chart; + return result; } public async getChartValues(repoName: string, chartName: string, version = "") { - const repo = await repoManager.repository(repoName) - const chartManager = new HelmChartManager(repo) - return chartManager.getValues(chartName, version) + const repo = await repoManager.repository(repoName); + const chartManager = new HelmChartManager(repo); + return chartManager.getValues(chartName, version); } public async listReleases(cluster: Cluster, namespace: string = null) { - await repoManager.init() - return await releaseManager.listReleases(cluster.getProxyKubeconfigPath(), namespace) + await repoManager.init(); + return await releaseManager.listReleases(cluster.getProxyKubeconfigPath(), namespace); } public async getRelease(cluster: Cluster, releaseName: string, namespace: string) { - logger.debug("Fetch release") - return await releaseManager.getRelease(releaseName, namespace, cluster) + logger.debug("Fetch release"); + return await releaseManager.getRelease(releaseName, namespace, cluster); } public async getReleaseValues(cluster: Cluster, releaseName: string, namespace: string) { - logger.debug("Fetch release values") - return await releaseManager.getValues(releaseName, namespace, cluster.getProxyKubeconfigPath()) + logger.debug("Fetch release values"); + return await releaseManager.getValues(releaseName, namespace, cluster.getProxyKubeconfigPath()); } public async getReleaseHistory(cluster: Cluster, releaseName: string, namespace: string) { - logger.debug("Fetch release history") - return await releaseManager.getHistory(releaseName, namespace, cluster.getProxyKubeconfigPath()) + logger.debug("Fetch release history"); + return await releaseManager.getHistory(releaseName, namespace, cluster.getProxyKubeconfigPath()); } public async deleteRelease(cluster: Cluster, releaseName: string, namespace: string) { - logger.debug("Delete release") - return await releaseManager.deleteRelease(releaseName, namespace, cluster.getProxyKubeconfigPath()) + logger.debug("Delete release"); + return await releaseManager.deleteRelease(releaseName, namespace, cluster.getProxyKubeconfigPath()); } public async updateRelease(cluster: Cluster, releaseName: string, namespace: string, data: { chart: string; values: {}; version: string }) { - logger.debug("Upgrade release") - return await releaseManager.upgradeRelease(releaseName, data.chart, data.values, namespace, data.version, cluster) + logger.debug("Upgrade release"); + return await releaseManager.upgradeRelease(releaseName, data.chart, data.values, namespace, data.version, cluster); } public async rollback(cluster: Cluster, releaseName: string, namespace: string, revision: number) { - logger.debug("Rollback release") - const output = await releaseManager.rollback(releaseName, namespace, revision, cluster.getProxyKubeconfigPath()) - return { message: output } + logger.debug("Rollback release"); + const output = await releaseManager.rollback(releaseName, namespace, revision, cluster.getProxyKubeconfigPath()); + return { message: output }; } protected excludeDeprecated(entries: any) { 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 - }) + return entry["deprecated"] != true; + }); } - return entries + return entries; } } -export const helmService = new HelmService() +export const helmService = new HelmService(); diff --git a/src/main/index.ts b/src/main/index.ts index e360c2fe85..2087432d7b 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,25 +1,25 @@ // Main process -import "../common/system-ca" -import "../common/prometheus-providers" -import * as Mobx from "mobx" +import "../common/system-ca"; +import "../common/prometheus-providers"; +import * as Mobx from "mobx"; import * as LensExtensions from "../extensions/core-api"; -import { app, dialog } from "electron" +import { app, dialog } from "electron"; import { appName } from "../common/vars"; -import path from "path" -import { LensProxy } from "./lens-proxy" +import path from "path"; +import { LensProxy } from "./lens-proxy"; import { WindowManager } from "./window-manager"; import { ClusterManager } from "./cluster-manager"; -import { AppUpdater } from "./app-updater" -import { shellSync } from "./shell-sync" -import { getFreePort } from "./port" -import { mangleProxyEnv } from "./proxy-env" +import { AppUpdater } from "./app-updater"; +import { shellSync } from "./shell-sync"; +import { getFreePort } from "./port"; +import { mangleProxyEnv } from "./proxy-env"; import { registerFileProtocol } from "../common/register-protocol"; -import logger from "./logger" -import { clusterStore } from "../common/cluster-store" +import logger from "./logger"; +import { clusterStore } from "../common/cluster-store"; import { userStore } from "../common/user-store"; import { workspaceStore } from "../common/workspace-store"; -import { appEventBus } from "../common/event-bus" +import { appEventBus } from "../common/event-bus"; import { extensionLoader } from "../extensions/extension-loader"; import { extensionManager } from "../extensions/extension-manager"; import { extensionsStore } from "../extensions/extensions-store"; @@ -35,16 +35,16 @@ if (!process.env.CICD) { app.setPath("userData", workingDir); } -mangleProxyEnv() +mangleProxyEnv(); if (app.commandLine.getSwitchValue("proxy-server") !== "") { - process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server") + process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server"); } app.on("ready", async () => { - logger.info(`🚀 Starting Lens from "${workingDir}"`) + logger.info(`🚀 Starting Lens from "${workingDir}"`); await shellSync(); - const updater = new AppUpdater() + const updater = new AppUpdater(); updater.start(); registerFileProtocol("static", __static); @@ -59,10 +59,10 @@ app.on("ready", async () => { // find free port try { - proxyPort = await getFreePort() + proxyPort = await getFreePort(); } catch (error) { - logger.error(error) - dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy") + logger.error(error); + dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy"); app.exit(); } @@ -73,22 +73,22 @@ app.on("ready", async () => { try { proxyServer = LensProxy.create(proxyPort, clusterManager); } catch (error) { - logger.error(`Could not start proxy (127.0.0:${proxyPort}): ${error.message}`) - dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${proxyPort}): ${error.message || "unknown error"}`) + logger.error(`Could not start proxy (127.0.0:${proxyPort}): ${error.message}`); + dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${proxyPort}): ${error.message || "unknown error"}`); app.exit(); } - extensionLoader.init() + extensionLoader.init(); windowManager = WindowManager.getInstance(proxyPort); extensionLoader.initExtensions(await extensionManager.load()); // call after windowManager to see splash earlier setTimeout(() => { - appEventBus.emit({ name: "service", action: "start" }) - }, 1000) + appEventBus.emit({ name: "service", action: "start" }); + }, 1000); }); app.on("activate", (event, hasVisibleWindows) => { - logger.info('APP:ACTIVATE', { hasVisibleWindows }) + logger.info('APP:ACTIVATE', { hasVisibleWindows }); if (!hasVisibleWindows) { windowManager.initMainWindow(); } @@ -97,11 +97,11 @@ app.on("activate", (event, hasVisibleWindows) => { // Quit app on Cmd+Q (MacOS) app.on("will-quit", (event) => { logger.info('APP:QUIT'); - appEventBus.emit({name: "app", action: "close"}) + appEventBus.emit({name: "app", action: "close"}); event.preventDefault(); // prevent app's default shutdown (e.g. required for telemetry, etc.) clusterManager?.stop(); // close cluster connections return; // skip exit to make tray work, to quit go to app's global menu or tray's menu -}) +}); // Extensions-api runtime exports export const LensExtensionsApi = { @@ -111,4 +111,4 @@ export const LensExtensionsApi = { export { Mobx, LensExtensionsApi as LensExtensions, -} +}; diff --git a/src/main/kube-auth-proxy.ts b/src/main/kube-auth-proxy.ts index 5377ecb829..3ad76e52b0 100644 --- a/src/main/kube-auth-proxy.ts +++ b/src/main/kube-auth-proxy.ts @@ -1,10 +1,10 @@ -import { ChildProcess, spawn } from "child_process" +import { ChildProcess, spawn } from "child_process"; import { waitUntilUsed } from "tcp-port-used"; import { broadcastMessage } from "../common/ipc"; -import type { Cluster } from "./cluster" -import { Kubectl } from "./kubectl" -import logger from "./logger" -import * as url from "url" +import type { Cluster } from "./cluster"; +import { Kubectl } from "./kubectl"; +import logger from "./logger"; +import * as url from "url"; export interface KubeAuthProxyLog { data: string; @@ -12,19 +12,19 @@ export interface KubeAuthProxyLog { } export class KubeAuthProxy { - public lastError: string + public lastError: string; - protected cluster: Cluster - protected env: NodeJS.ProcessEnv = null - protected proxyProcess: ChildProcess - protected port: number - protected kubectl: Kubectl + protected cluster: Cluster; + protected env: NodeJS.ProcessEnv = null; + protected proxyProcess: ChildProcess; + protected port: number; + protected kubectl: Kubectl; constructor(cluster: Cluster, port: number, env: NodeJS.ProcessEnv) { - this.env = env - this.port = port - this.cluster = cluster - this.kubectl = Kubectl.bundled() + this.env = env; + this.port = port; + this.cluster = cluster; + this.kubectl = Kubectl.bundled(); } get acceptHosts() { @@ -36,7 +36,7 @@ export class KubeAuthProxy { return; } - const proxyBin = await this.kubectl.getPath() + const proxyBin = await this.kubectl.getPath(); const args = [ "proxy", "-p", `${this.port}`, @@ -44,63 +44,63 @@ export class KubeAuthProxy { "--context", `${this.cluster.contextName}`, "--accept-hosts", this.acceptHosts, "--reject-paths", "^[^/]" - ] + ]; if (process.env.DEBUG_PROXY === "true") { - args.push("-v", "9") + args.push("-v", "9"); } - logger.debug(`spawning kubectl proxy with args: ${args}`) - this.proxyProcess = spawn(proxyBin, args, { env: this.env, }) + logger.debug(`spawning kubectl proxy with args: ${args}`); + this.proxyProcess = spawn(proxyBin, args, { env: this.env, }); this.proxyProcess.on("error", (error) => { - this.sendIpcLogMessage({ data: error.message, error: true }) - this.exit() - }) + this.sendIpcLogMessage({ data: error.message, error: true }); + this.exit(); + }); this.proxyProcess.on("exit", (code) => { - this.sendIpcLogMessage({ data: `proxy exited with code: ${code}`, error: code > 0 }) + this.sendIpcLogMessage({ data: `proxy exited with code: ${code}`, error: code > 0 }); this.exit(); - }) + }); this.proxyProcess.stdout.on('data', (data) => { - let logItem = data.toString() + let logItem = data.toString(); if (logItem.startsWith("Starting to serve on")) { - logItem = "Authentication proxy started\n" + logItem = "Authentication proxy started\n"; } - this.sendIpcLogMessage({ data: logItem }) - }) + this.sendIpcLogMessage({ data: logItem }); + }); this.proxyProcess.stderr.on('data', (data) => { - this.lastError = this.parseError(data.toString()) - this.sendIpcLogMessage({ data: data.toString(), error: true }) - }) + this.lastError = this.parseError(data.toString()); + this.sendIpcLogMessage({ data: data.toString(), error: true }); + }); - return waitUntilUsed(this.port, 500, 10000) + return waitUntilUsed(this.port, 500, 10000); } protected parseError(data: string) { - const error = data.split("http: proxy error:").slice(1).join("").trim() - let errorMsg = error - const jsonError = error.split("Response: ")[1] + const error = data.split("http: proxy error:").slice(1).join("").trim(); + let errorMsg = error; + const jsonError = error.split("Response: ")[1]; if (jsonError) { try { - const parsedError = JSON.parse(jsonError) - errorMsg = parsedError.error_description || parsedError.error || jsonError + const parsedError = JSON.parse(jsonError); + errorMsg = parsedError.error_description || parsedError.error || jsonError; } catch (_) { - errorMsg = jsonError.trim() + errorMsg = jsonError.trim(); } } - return errorMsg + return errorMsg; } protected async sendIpcLogMessage(res: KubeAuthProxyLog) { - const channel = `kube-auth:${this.cluster.id}` + const channel = `kube-auth:${this.cluster.id}`; logger.info(`[KUBE-AUTH]: out-channel "${channel}"`, { ...res, meta: this.cluster.getMeta() }); - broadcastMessage(channel, res) + broadcastMessage(channel, res); } public exit() { if (!this.proxyProcess) return; - logger.debug("[KUBE-AUTH]: stopping local proxy", this.cluster.getMeta()) - this.proxyProcess.kill() + logger.debug("[KUBE-AUTH]: stopping local proxy", this.cluster.getMeta()); + this.proxyProcess.kill(); this.proxyProcess.removeAllListeners(); this.proxyProcess.stderr.removeAllListeners(); this.proxyProcess.stdout.removeAllListeners(); diff --git a/src/main/kubeconfig-manager.ts b/src/main/kubeconfig-manager.ts index fc84d00ddb..a8b3ae3fce 100644 --- a/src/main/kubeconfig-manager.ts +++ b/src/main/kubeconfig-manager.ts @@ -1,22 +1,22 @@ import type { KubeConfig } from "@kubernetes/client-node"; -import type { Cluster } from "./cluster" +import type { Cluster } from "./cluster"; import type { ContextHandler } from "./context-handler"; -import { app } from "electron" -import path from "path" -import fs from "fs-extra" -import { dumpConfigYaml, loadConfig } from "../common/kube-helpers" -import logger from "./logger" +import { app } from "electron"; +import path from "path"; +import fs from "fs-extra"; +import { dumpConfigYaml, loadConfig } from "../common/kube-helpers"; +import logger from "./logger"; export class KubeconfigManager { - protected configDir = app.getPath("temp") + protected configDir = app.getPath("temp"); protected tempFile: string; private constructor(protected cluster: Cluster, protected contextHandler: ContextHandler, protected port: number) { } static async create(cluster: Cluster, contextHandler: ContextHandler, port: number) { - const kcm = new KubeconfigManager(cluster, contextHandler, port) - await kcm.init() - return kcm + const kcm = new KubeconfigManager(cluster, contextHandler, port); + await kcm.init(); + return kcm; } protected async init() { @@ -24,7 +24,7 @@ export class KubeconfigManager { await this.contextHandler.ensurePort(); await this.createProxyKubeconfig(); } catch (err) { - logger.error(`Failed to created temp config for auth-proxy`, { err }) + logger.error(`Failed to created temp config for auth-proxy`, { err }); } } @@ -33,7 +33,7 @@ export class KubeconfigManager { } protected resolveProxyUrl() { - return `http://127.0.0.1:${this.port}/${this.cluster.id}` + return `http://127.0.0.1:${this.port}/${this.cluster.id}`; } /** @@ -78,11 +78,11 @@ export class KubeconfigManager { async unlink() { if (!this.tempFile) { - return + return; } - logger.info('Deleting temporary kubeconfig: ' + this.tempFile) - await fs.unlink(this.tempFile) - this.tempFile = undefined + logger.info('Deleting temporary kubeconfig: ' + this.tempFile); + await fs.unlink(this.tempFile); + this.tempFile = undefined; } } diff --git a/src/main/kubectl.ts b/src/main/kubectl.ts index 6b2f51476d..5d3f12746e 100644 --- a/src/main/kubectl.ts +++ b/src/main/kubectl.ts @@ -1,17 +1,17 @@ -import { app, remote } from "electron" -import path from "path" -import fs from "fs" -import { promiseExec } from "./promise-exec" -import logger from "./logger" -import { ensureDir, pathExists } from "fs-extra" -import * as lockFile from "proper-lockfile" -import { helmCli } from "./helm/helm-cli" -import { userStore } from "../common/user-store" +import { app, remote } from "electron"; +import path from "path"; +import fs from "fs"; +import { promiseExec } from "./promise-exec"; +import logger from "./logger"; +import { ensureDir, pathExists } from "fs-extra"; +import * as lockFile from "proper-lockfile"; +import { helmCli } from "./helm/helm-cli"; +import { userStore } from "../common/user-store"; import { customRequest } from "../common/request"; -import { getBundledKubectlVersion } from "../common/utils/app-version" +import { getBundledKubectlVersion } from "../common/utils/app-version"; import { isDevelopment, isWindows, isTestEnv } from "../common/vars"; -const bundledVersion = getBundledKubectlVersion() +const bundledVersion = getBundledKubectlVersion(); const kubectlMap: Map = new Map([ ["1.7", "1.8.15"], ["1.8", "1.9.10"], @@ -26,314 +26,314 @@ const kubectlMap: Map = new Map([ ["1.17", bundledVersion], ["1.18", "1.18.8"], ["1.19", "1.19.0"] -]) +]); const packageMirrors: Map = new Map([ ["default", "https://storage.googleapis.com/kubernetes-release/release"], ["china", "https://mirror.azure.cn/kubernetes/kubectl"] -]) +]); -let bundledPath: string -const initScriptVersionString = "# lens-initscript v3\n" +let bundledPath: string; +const initScriptVersionString = "# lens-initscript v3\n"; export function bundledKubectlPath(): string { - if (bundledPath) { return bundledPath } + if (bundledPath) { return bundledPath; } if (isDevelopment || isTestEnv) { - const platformName = isWindows ? "windows" : process.platform - bundledPath = path.join(process.cwd(), "binaries", "client", platformName, process.arch, "kubectl") + const platformName = isWindows ? "windows" : process.platform; + bundledPath = path.join(process.cwd(), "binaries", "client", platformName, process.arch, "kubectl"); } else { - bundledPath = path.join(process.resourcesPath, process.arch, "kubectl") + bundledPath = path.join(process.resourcesPath, process.arch, "kubectl"); } if (isWindows) { - bundledPath = `${bundledPath}.exe` + bundledPath = `${bundledPath}.exe`; } - return bundledPath + return bundledPath; } export class Kubectl { - public kubectlVersion: string - protected directory: string - protected url: string - protected path: string - protected dirname: string + public kubectlVersion: string; + protected directory: string; + protected url: string; + protected path: string; + protected dirname: string; static get kubectlDir() { - return path.join((app || remote.app).getPath("userData"), "binaries", "kubectl") + return path.join((app || remote.app).getPath("userData"), "binaries", "kubectl"); } - public static readonly bundledKubectlVersion: string = bundledVersion - public static invalidBundle = false + public static readonly bundledKubectlVersion: string = bundledVersion; + public static invalidBundle = false; private static bundledInstance: Kubectl; // Returns the single bundled Kubectl instance public static bundled() { - if (!Kubectl.bundledInstance) Kubectl.bundledInstance = new Kubectl(Kubectl.bundledKubectlVersion) - return Kubectl.bundledInstance + if (!Kubectl.bundledInstance) Kubectl.bundledInstance = new Kubectl(Kubectl.bundledKubectlVersion); + return Kubectl.bundledInstance; } constructor(clusterVersion: string) { - const versionParts = /^v?(\d+\.\d+)(.*)/.exec(clusterVersion) - const minorVersion = versionParts[1] + const versionParts = /^v?(\d+\.\d+)(.*)/.exec(clusterVersion); + const minorVersion = versionParts[1]; /* minorVersion is the first two digits of kube server version if the version map includes that, use that version, if not, fallback to the exact x.y.z of kube version */ if (kubectlMap.has(minorVersion)) { - this.kubectlVersion = kubectlMap.get(minorVersion) - logger.debug("Set kubectl version " + this.kubectlVersion + " for cluster version " + clusterVersion + " using version map") + this.kubectlVersion = kubectlMap.get(minorVersion); + logger.debug("Set kubectl version " + this.kubectlVersion + " for cluster version " + clusterVersion + " using version map"); } else { - this.kubectlVersion = versionParts[1] + versionParts[2] - logger.debug("Set kubectl version " + this.kubectlVersion + " for cluster version " + clusterVersion + " using fallback") + this.kubectlVersion = versionParts[1] + versionParts[2]; + logger.debug("Set kubectl version " + this.kubectlVersion + " for cluster version " + clusterVersion + " using fallback"); } - let arch = null + let arch = null; if (process.arch == "x64") { - arch = "amd64" + arch = "amd64"; } else if (process.arch == "x86" || process.arch == "ia32") { - arch = "386" + arch = "386"; } else { - arch = process.arch + arch = process.arch; } - const platformName = isWindows ? "windows" : process.platform - const binaryName = isWindows ? "kubectl.exe" : "kubectl" + const platformName = isWindows ? "windows" : process.platform; + const binaryName = isWindows ? "kubectl.exe" : "kubectl"; - this.url = `${this.getDownloadMirror()}/v${this.kubectlVersion}/bin/${platformName}/${arch}/${binaryName}` + this.url = `${this.getDownloadMirror()}/v${this.kubectlVersion}/bin/${platformName}/${arch}/${binaryName}`; - this.dirname = path.normalize(path.join(this.getDownloadDir(), this.kubectlVersion)) - this.path = path.join(this.dirname, binaryName) + this.dirname = path.normalize(path.join(this.getDownloadDir(), this.kubectlVersion)); + this.path = path.join(this.dirname, binaryName); } public getBundledPath() { - return bundledKubectlPath() + return bundledKubectlPath(); } public getPathFromPreferences() { - return userStore.preferences?.kubectlBinariesPath || this.getBundledPath() + return userStore.preferences?.kubectlBinariesPath || this.getBundledPath(); } protected getDownloadDir() { if (userStore.preferences?.downloadBinariesPath) { - return path.join(userStore.preferences.downloadBinariesPath, "kubectl") + return path.join(userStore.preferences.downloadBinariesPath, "kubectl"); } - return Kubectl.kubectlDir + return Kubectl.kubectlDir; } public async getPath(bundled = false): Promise { if (userStore.preferences?.downloadKubectlBinaries === false) { - return this.getPathFromPreferences() + return this.getPathFromPreferences(); } // return binary name if bundled path is not functional if (!await this.checkBinary(this.getBundledPath(), false)) { - Kubectl.invalidBundle = true - return path.basename(this.getBundledPath()) + Kubectl.invalidBundle = true; + return path.basename(this.getBundledPath()); } try { if (!await this.ensureKubectl()) { - logger.error("Failed to ensure kubectl, fallback to the bundled version") - return this.getBundledPath() + logger.error("Failed to ensure kubectl, fallback to the bundled version"); + return this.getBundledPath(); } - return this.path + return this.path; } catch (err) { - logger.error("Failed to ensure kubectl, fallback to the bundled version") - logger.error(err) - return this.getBundledPath() + logger.error("Failed to ensure kubectl, fallback to the bundled version"); + logger.error(err); + return this.getBundledPath(); } } public async binDir() { try { - await this.ensureKubectl() - await this.writeInitScripts() - return this.dirname + await this.ensureKubectl(); + await this.writeInitScripts(); + return this.dirname; } catch (err) { - logger.error(err) - return "" + logger.error(err); + return ""; } } public async checkBinary(path: string, checkVersion = true) { - const exists = await pathExists(path) + const exists = await pathExists(path); if (exists) { try { - const { stdout } = await promiseExec(`"${path}" version --client=true -o json`) - const output = JSON.parse(stdout) + const { stdout } = await promiseExec(`"${path}" version --client=true -o json`); + const output = JSON.parse(stdout); if (!checkVersion) { - return true + return true; } - let version: string = output.clientVersion.gitVersion + let version: string = output.clientVersion.gitVersion; if (version[0] === 'v') { - version = version.slice(1) + version = version.slice(1); } if (version === this.kubectlVersion) { - logger.debug(`Local kubectl is version ${this.kubectlVersion}`) - return true + logger.debug(`Local kubectl is version ${this.kubectlVersion}`); + return true; } - logger.error(`Local kubectl is version ${version}, expected ${this.kubectlVersion}, unlinking`) + logger.error(`Local kubectl is version ${version}, expected ${this.kubectlVersion}, unlinking`); } catch (err) { - logger.error(`Local kubectl failed to run properly (${err.message}), unlinking`) + logger.error(`Local kubectl failed to run properly (${err.message}), unlinking`); } - await fs.promises.unlink(this.path) + await fs.promises.unlink(this.path); } - return false + return false; } protected async checkBundled(): Promise { if (this.kubectlVersion === Kubectl.bundledKubectlVersion) { try { - const exist = await pathExists(this.path) + const exist = await pathExists(this.path); if (!exist) { - await fs.promises.copyFile(this.getBundledPath(), this.path) - await fs.promises.chmod(this.path, 0o755) + await fs.promises.copyFile(this.getBundledPath(), this.path); + await fs.promises.chmod(this.path, 0o755); } - return true + return true; } catch (err) { - logger.error("Could not copy the bundled kubectl to app-data: " + err) - return false + logger.error("Could not copy the bundled kubectl to app-data: " + err); + return false; } } else { - return false + return false; } } public async ensureKubectl(): Promise { if (userStore.preferences?.downloadKubectlBinaries === false) { - return true + return true; } if (Kubectl.invalidBundle) { - logger.error(`Detected invalid bundle binary, returning ...`) - return false + logger.error(`Detected invalid bundle binary, returning ...`); + return false; } - await ensureDir(this.dirname, 0o755) + await ensureDir(this.dirname, 0o755); return lockFile.lock(this.dirname).then(async (release) => { - logger.debug(`Acquired a lock for ${this.kubectlVersion}`) - const bundled = await this.checkBundled() - let isValid = await this.checkBinary(this.path, !bundled) + logger.debug(`Acquired a lock for ${this.kubectlVersion}`); + const bundled = await this.checkBundled(); + let isValid = await this.checkBinary(this.path, !bundled); if (!isValid && !bundled) { await this.downloadKubectl().catch((error) => { - logger.error(error) - logger.debug(`Releasing lock for ${this.kubectlVersion}`) - release() - return false + logger.error(error); + logger.debug(`Releasing lock for ${this.kubectlVersion}`); + release(); + return false; }); - isValid = !await this.checkBinary(this.path, false) + isValid = !await this.checkBinary(this.path, false); } if (!isValid) { - logger.debug(`Releasing lock for ${this.kubectlVersion}`) - release() - return false + logger.debug(`Releasing lock for ${this.kubectlVersion}`); + release(); + return false; } - logger.debug(`Releasing lock for ${this.kubectlVersion}`) - release() - return true + logger.debug(`Releasing lock for ${this.kubectlVersion}`); + release(); + return true; }).catch((e) => { - logger.error(`Failed to get a lock for ${this.kubectlVersion}`) - logger.error(e) - return false - }) + logger.error(`Failed to get a lock for ${this.kubectlVersion}`); + logger.error(e); + return false; + }); } public async downloadKubectl() { - await ensureDir(path.dirname(this.path), 0o755) + await ensureDir(path.dirname(this.path), 0o755); - logger.info(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`) + logger.info(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`); return new Promise((resolve, reject) => { const stream = customRequest({ url: this.url, gzip: true, }); - const file = fs.createWriteStream(this.path) + const file = fs.createWriteStream(this.path); stream.on("complete", () => { - logger.debug("kubectl binary download finished") - file.end() - }) + logger.debug("kubectl binary download finished"); + file.end(); + }); stream.on("error", (error) => { - logger.error(error) + logger.error(error); fs.unlink(this.path, () => { // do nothing - }) - reject(error) - }) + }); + reject(error); + }); file.on("close", () => { - logger.debug("kubectl binary download closed") + logger.debug("kubectl binary download closed"); fs.chmod(this.path, 0o755, (err) => { if (err) reject(err); - }) - resolve() - }) - stream.pipe(file) - }) + }); + resolve(); + }); + stream.pipe(file); + }); } protected async writeInitScripts() { - const kubectlPath = userStore.preferences?.downloadKubectlBinaries ? this.dirname : path.dirname(this.getPathFromPreferences()) - const helmPath = helmCli.getBinaryDir() + 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" - bashScript += "test -f \"/etc/profile\" && . \"/etc/profile\"\n" - bashScript += "if test -f \"$HOME/.bash_profile\"; then\n" - bashScript += " . \"$HOME/.bash_profile\"\n" - bashScript += "elif test -f \"$HOME/.bash_login\"; then\n" - bashScript += " . \"$HOME/.bash_login\"\n" - bashScript += "elif test -f \"$HOME/.profile\"; then\n" - bashScript += " . \"$HOME/.profile\"\n" - bashScript += "fi\n" - bashScript += `export PATH="${helmPath}:${kubectlPath}:$PATH"\n` - bashScript += "export KUBECONFIG=\"$tempkubeconfig\"\n" + let bashScript = "" + initScriptVersionString; + bashScript += "tempkubeconfig=\"$KUBECONFIG\"\n"; + bashScript += "test -f \"/etc/profile\" && . \"/etc/profile\"\n"; + bashScript += "if test -f \"$HOME/.bash_profile\"; then\n"; + bashScript += " . \"$HOME/.bash_profile\"\n"; + bashScript += "elif test -f \"$HOME/.bash_login\"; then\n"; + bashScript += " . \"$HOME/.bash_login\"\n"; + bashScript += "elif test -f \"$HOME/.profile\"; then\n"; + bashScript += " . \"$HOME/.profile\"\n"; + bashScript += "fi\n"; + bashScript += `export PATH="${helmPath}:${kubectlPath}:$PATH"\n`; + bashScript += "export KUBECONFIG=\"$tempkubeconfig\"\n"; - bashScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n" - bashScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n" - bashScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n" - bashScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n" - bashScript += "export NO_PROXY\n" - bashScript += "unset tempkubeconfig\n" - await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 }) + bashScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n"; + bashScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n"; + bashScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n"; + bashScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n"; + bashScript += "export NO_PROXY\n"; + 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 + let zshScript = "" + initScriptVersionString; - zshScript += "tempkubeconfig=\"$KUBECONFIG\"\n" + zshScript += "tempkubeconfig=\"$KUBECONFIG\"\n"; // restore previous ZDOTDIR - zshScript += "export ZDOTDIR=\"$OLD_ZDOTDIR\"\n" + zshScript += "export ZDOTDIR=\"$OLD_ZDOTDIR\"\n"; // source all the files - zshScript += "test -f \"$OLD_ZDOTDIR/.zshenv\" && . \"$OLD_ZDOTDIR/.zshenv\"\n" - zshScript += "test -f \"$OLD_ZDOTDIR/.zprofile\" && . \"$OLD_ZDOTDIR/.zprofile\"\n" - zshScript += "test -f \"$OLD_ZDOTDIR/.zlogin\" && . \"$OLD_ZDOTDIR/.zlogin\"\n" - zshScript += "test -f \"$OLD_ZDOTDIR/.zshrc\" && . \"$OLD_ZDOTDIR/.zshrc\"\n" + zshScript += "test -f \"$OLD_ZDOTDIR/.zshenv\" && . \"$OLD_ZDOTDIR/.zshenv\"\n"; + zshScript += "test -f \"$OLD_ZDOTDIR/.zprofile\" && . \"$OLD_ZDOTDIR/.zprofile\"\n"; + zshScript += "test -f \"$OLD_ZDOTDIR/.zlogin\" && . \"$OLD_ZDOTDIR/.zlogin\"\n"; + zshScript += "test -f \"$OLD_ZDOTDIR/.zshrc\" && . \"$OLD_ZDOTDIR/.zshrc\"\n"; // voodoo to replace any previous occurrences of kubectl path in the PATH - zshScript += `kubectlpath=\"${kubectlPath}"\n` - zshScript += `helmpath=\"${helmPath}"\n` - zshScript += "p=\":$kubectlpath:\"\n" - zshScript += "d=\":$PATH:\"\n" - zshScript += "d=${d//$p/:}\n" - zshScript += "d=${d/#:/}\n" - zshScript += "export PATH=\"$helmpath:$kubectlpath:${d/%:/}\"\n" - zshScript += "export KUBECONFIG=\"$tempkubeconfig\"\n" - zshScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n" - zshScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n" - zshScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n" - zshScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n" - zshScript += "export NO_PROXY\n" - zshScript += "unset tempkubeconfig\n" - zshScript += "unset OLD_ZDOTDIR\n" - await fsPromises.writeFile(zshScriptPath, zshScript.toString(), { mode: 0o644 }) + zshScript += `kubectlpath=\"${kubectlPath}"\n`; + zshScript += `helmpath=\"${helmPath}"\n`; + zshScript += "p=\":$kubectlpath:\"\n"; + zshScript += "d=\":$PATH:\"\n"; + zshScript += "d=${d//$p/:}\n"; + zshScript += "d=${d/#:/}\n"; + zshScript += "export PATH=\"$helmpath:$kubectlpath:${d/%:/}\"\n"; + zshScript += "export KUBECONFIG=\"$tempkubeconfig\"\n"; + zshScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n"; + zshScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n"; + zshScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n"; + zshScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n"; + zshScript += "export NO_PROXY\n"; + zshScript += "unset tempkubeconfig\n"; + zshScript += "unset OLD_ZDOTDIR\n"; + await fsPromises.writeFile(zshScriptPath, zshScript.toString(), { mode: 0o644 }); } protected getDownloadMirror() { - const mirror = packageMirrors.get(userStore.preferences?.downloadMirror) + const mirror = packageMirrors.get(userStore.preferences?.downloadMirror); if (mirror) { - return mirror + return mirror; } - return packageMirrors.get("default") // MacOS packages are only available from default + return packageMirrors.get("default"); // MacOS packages are only available from default } } diff --git a/src/main/kubectl_spec.ts b/src/main/kubectl_spec.ts index ade999c082..9d5a5d1e1d 100644 --- a/src/main/kubectl_spec.ts +++ b/src/main/kubectl_spec.ts @@ -1,5 +1,5 @@ -import packageInfo from "../../package.json" -import path from "path" +import packageInfo from "../../package.json"; +import path from "path"; import { Kubectl } from "../../src/main/kubectl"; import { isWindows } from "../common/vars"; @@ -7,39 +7,39 @@ jest.mock("../common/user-store"); describe("kubectlVersion", () => { it("returns bundled version if exactly same version used", async () => { - const kubectl = new Kubectl(Kubectl.bundled().kubectlVersion) - expect(kubectl.kubectlVersion).toBe(Kubectl.bundled().kubectlVersion) - }) + const kubectl = new Kubectl(Kubectl.bundled().kubectlVersion); + expect(kubectl.kubectlVersion).toBe(Kubectl.bundled().kubectlVersion); + }); it("returns bundled version if same major.minor version is used", async () => { const { bundledKubectlVersion } = packageInfo.config; const kubectl = new Kubectl(bundledKubectlVersion); - expect(kubectl.kubectlVersion).toBe(Kubectl.bundled().kubectlVersion) - }) -}) + expect(kubectl.kubectlVersion).toBe(Kubectl.bundled().kubectlVersion); + }); +}); describe("getPath()", () => { it("returns path to downloaded kubectl binary", async () => { const { bundledKubectlVersion } = packageInfo.config; const kubectl = new Kubectl(bundledKubectlVersion); - const kubectlPath = await kubectl.getPath() - let binaryName = "kubectl" + const kubectlPath = await kubectl.getPath(); + let binaryName = "kubectl"; if (isWindows) { - binaryName += ".exe" + binaryName += ".exe"; } - const expectedPath = path.join(Kubectl.kubectlDir, Kubectl.bundledKubectlVersion, binaryName) - expect(kubectlPath).toBe(expectedPath) - }) + const expectedPath = path.join(Kubectl.kubectlDir, Kubectl.bundledKubectlVersion, binaryName); + expect(kubectlPath).toBe(expectedPath); + }); it("returns plain binary name if bundled kubectl is non-functional", async () => { const { bundledKubectlVersion } = packageInfo.config; const kubectl = new Kubectl(bundledKubectlVersion); - jest.spyOn(kubectl, "getBundledPath").mockReturnValue("/invalid/path/kubectl") - const kubectlPath = await kubectl.getPath() - let binaryName = "kubectl" + jest.spyOn(kubectl, "getBundledPath").mockReturnValue("/invalid/path/kubectl"); + const kubectlPath = await kubectl.getPath(); + let binaryName = "kubectl"; if (isWindows) { - binaryName += ".exe" + binaryName += ".exe"; } - expect(kubectlPath).toBe(binaryName) - }) -}) + expect(kubectlPath).toBe(binaryName); + }); +}); diff --git a/src/main/lens-api.ts b/src/main/lens-api.ts index a0a7361a68..fafeffce91 100644 --- a/src/main/lens-api.ts +++ b/src/main/lens-api.ts @@ -2,16 +2,16 @@ import http from "http"; export abstract class LensApi { protected respondJson(res: http.ServerResponse, content: {}, status = 200) { - this.respond(res, JSON.stringify(content), "application/json", status) + this.respond(res, JSON.stringify(content), "application/json", status); } protected respondText(res: http.ServerResponse, content: string, status = 200) { - this.respond(res, content, "text/plain", status) + this.respond(res, content, "text/plain", status); } protected respond(res: http.ServerResponse, content: string, contentType: string, status = 200) { - res.setHeader("Content-Type", contentType) - res.statusCode = status - res.end(content) + res.setHeader("Content-Type", contentType); + res.statusCode = status; + res.end(content); } } diff --git a/src/main/lens-binary.ts b/src/main/lens-binary.ts index dd6f2aa058..fc6b59ee74 100644 --- a/src/main/lens-binary.ts +++ b/src/main/lens-binary.ts @@ -1,10 +1,10 @@ -import path from "path" -import fs from "fs" -import request from "request" -import { ensureDir, pathExists } from "fs-extra" -import * as tar from "tar" +import path from "path"; +import fs from "fs"; +import request from "request"; +import { ensureDir, pathExists } from "fs-extra"; +import * as tar from "tar"; import { isWindows } from "../common/vars"; -import winston from "winston" +import winston from "winston"; export type LensBinaryOpts = { version: string; @@ -12,177 +12,177 @@ export type LensBinaryOpts = { originalBinaryName: string; newBinaryName?: string; requestOpts?: request.Options; -} +}; export class LensBinary { - public binaryVersion: string - protected directory: string - protected url: string + public binaryVersion: string; + protected directory: string; + protected url: string; protected path: string; protected tarPath: string; - protected dirname: string - protected binaryName: string - protected platformName: string - protected arch: string - protected originalBinaryName: string - protected requestOpts: request.Options - protected logger: Console | winston.Logger + protected dirname: string; + protected binaryName: string; + protected platformName: string; + protected arch: string; + protected originalBinaryName: string; + protected requestOpts: request.Options; + protected logger: Console | winston.Logger; constructor(opts: LensBinaryOpts) { - const baseDir = opts.baseDir - this.originalBinaryName = opts.originalBinaryName - this.binaryName = opts.newBinaryName || opts.originalBinaryName - this.binaryVersion = opts.version - this.requestOpts = opts.requestOpts - this.logger = console - let arch = null + const baseDir = opts.baseDir; + this.originalBinaryName = opts.originalBinaryName; + this.binaryName = opts.newBinaryName || opts.originalBinaryName; + this.binaryVersion = opts.version; + this.requestOpts = opts.requestOpts; + this.logger = console; + let arch = null; if (process.arch == "x64") { - arch = "amd64" + arch = "amd64"; } else if (process.arch == "x86" || process.arch == "ia32") { - arch = "386" + arch = "386"; } else { - arch = process.arch + arch = process.arch; } - this.arch = arch - this.platformName = isWindows ? "windows" : process.platform - this.dirname = path.normalize(path.join(baseDir, this.binaryName)) + this.arch = arch; + this.platformName = isWindows ? "windows" : process.platform; + this.dirname = path.normalize(path.join(baseDir, this.binaryName)); if (isWindows) { - this.binaryName = this.binaryName + ".exe" - this.originalBinaryName = this.originalBinaryName + ".exe" + this.binaryName = this.binaryName + ".exe"; + this.originalBinaryName = this.originalBinaryName + ".exe"; } - const tarName = this.getTarName() + const tarName = this.getTarName(); if (tarName) { - this.tarPath = path.join(this.dirname, tarName) + this.tarPath = path.join(this.dirname, tarName); } } public setLogger(logger: Console | winston.Logger) { - this.logger = logger + this.logger = logger; } protected binaryDir() { - throw new Error("binaryDir not implemented") + throw new Error("binaryDir not implemented"); } public async binaryPath() { - await this.ensureBinary() - return this.getBinaryPath() + await this.ensureBinary(); + return this.getBinaryPath(); } protected getTarName(): string | null { - return null + return null; } protected getUrl() { - return "" + return ""; } protected getBinaryPath() { - return "" + return ""; } protected getOriginalBinaryPath() { - return "" + return ""; } public getBinaryDir() { - return path.dirname(this.getBinaryPath()) + return path.dirname(this.getBinaryPath()); } public async binDir() { try { - await this.ensureBinary() - return this.dirname + await this.ensureBinary(); + return this.dirname; } catch (err) { - this.logger.error(err) - return "" + this.logger.error(err); + return ""; } } protected async checkBinary() { - const exists = await pathExists(this.getBinaryPath()) - return exists + const exists = await pathExists(this.getBinaryPath()); + return exists; } public async ensureBinary() { - const isValid = await this.checkBinary() + const isValid = await this.checkBinary(); if (!isValid) { await this.downloadBinary().catch((error) => { - this.logger.error(error) + this.logger.error(error); }); - if (this.tarPath) await this.untarBinary() - if (this.originalBinaryName != this.binaryName) await this.renameBinary() - this.logger.info(`${this.originalBinaryName} has been downloaded to ${this.getBinaryPath()}`) + if (this.tarPath) await this.untarBinary(); + if (this.originalBinaryName != this.binaryName) await this.renameBinary(); + this.logger.info(`${this.originalBinaryName} has been downloaded to ${this.getBinaryPath()}`); } } protected async untarBinary() { return new Promise((resolve, reject) => { - this.logger.debug(`Extracting ${this.originalBinaryName} binary`) + this.logger.debug(`Extracting ${this.originalBinaryName} binary`); tar.x({ file: this.tarPath, cwd: this.dirname }).then((_ => { - resolve() - })) - }) + resolve(); + })); + }); } protected async renameBinary() { return new Promise((resolve, reject) => { - this.logger.debug(`Renaming ${this.originalBinaryName} binary to ${this.binaryName}`) + this.logger.debug(`Renaming ${this.originalBinaryName} binary to ${this.binaryName}`); fs.rename(this.getOriginalBinaryPath(), this.getBinaryPath(), (err) => { if (err) { - reject(err) + reject(err); } else { - resolve() + resolve(); } - }) - }) + }); + }); } protected async downloadBinary() { - const binaryPath = this.tarPath || this.getBinaryPath() - await ensureDir(this.getBinaryDir(), 0o755) + const binaryPath = this.tarPath || this.getBinaryPath(); + await ensureDir(this.getBinaryDir(), 0o755); - const file = fs.createWriteStream(binaryPath) - const url = this.getUrl() + const file = fs.createWriteStream(binaryPath); + const url = this.getUrl(); - this.logger.info(`Downloading ${this.originalBinaryName} ${this.binaryVersion} from ${url} to ${binaryPath}`) + this.logger.info(`Downloading ${this.originalBinaryName} ${this.binaryVersion} from ${url} to ${binaryPath}`); const requestOpts: request.UriOptions & request.CoreOptions = { uri: url, gzip: true, ...this.requestOpts - } + }; - const stream = request(requestOpts) + const stream = request(requestOpts); stream.on("complete", () => { - this.logger.info(`Download of ${this.originalBinaryName} finished`) - file.end() - }) + this.logger.info(`Download of ${this.originalBinaryName} finished`); + file.end(); + }); stream.on("error", (error) => { - this.logger.error(error) + this.logger.error(error); fs.unlink(binaryPath, () => { // do nothing - }) - throw(error) - }) + }); + throw(error); + }); return new Promise((resolve, reject) => { file.on("close", () => { - this.logger.debug(`${this.originalBinaryName} binary download closed`) + this.logger.debug(`${this.originalBinaryName} binary download closed`); if (!this.tarPath) fs.chmod(binaryPath, 0o755, (err) => { if (err) reject(err); - }) - resolve() - }) - stream.pipe(file) - }) + }); + resolve(); + }); + stream.pipe(file); + }); } } diff --git a/src/main/lens-proxy.ts b/src/main/lens-proxy.ts index 7f0b14721d..03b1b15d29 100644 --- a/src/main/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -3,27 +3,27 @@ import http from "http"; import spdy from "spdy"; import httpProxy from "http-proxy"; import url from "url"; -import * as WebSocket from "ws" -import { apiPrefix, apiKubePrefix } from "../common/vars" +import * as WebSocket from "ws"; +import { apiPrefix, apiKubePrefix } from "../common/vars"; import { openShell } from "./node-shell-session"; -import { Router } from "./router" -import { ClusterManager } from "./cluster-manager" +import { Router } from "./router"; +import { ClusterManager } from "./cluster-manager"; import { ContextHandler } from "./context-handler"; -import logger from "./logger" +import logger from "./logger"; export class LensProxy { - protected origin: string - protected proxyServer: http.Server - protected router: Router - protected closed = false - protected retryCounters = new Map() + protected origin: string; + protected proxyServer: http.Server; + protected router: Router; + protected closed = false; + protected retryCounters = new Map(); static create(port: number, clusterManager: ClusterManager) { return new LensProxy(port, clusterManager).listen(); } private constructor(protected port: number, protected clusterManager: ClusterManager) { - this.origin = `http://localhost:${port}` + this.origin = `http://localhost:${port}`; this.router = new Router(); } @@ -35,8 +35,8 @@ export class LensProxy { close() { logger.info("Closing proxy server"); - this.proxyServer.close() - this.closed = true + this.proxyServer.close(); + this.closed = true; } protected buildCustomProxy(): http.Server { @@ -47,66 +47,66 @@ export class LensProxy { protocols: ["http/1.1", "spdy/3.1"] } }, (req: http.IncomingMessage, res: http.ServerResponse) => { - this.handleRequest(proxy, req, res) - }) + this.handleRequest(proxy, req, res); + }); spdyProxy.on("upgrade", (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => { if (req.url.startsWith(`${apiPrefix}?`)) { - this.handleWsUpgrade(req, socket, head) + this.handleWsUpgrade(req, socket, head); } else { - this.handleProxyUpgrade(proxy, req, socket, head) + this.handleProxyUpgrade(proxy, req, socket, head); } - }) + }); spdyProxy.on("error", (err) => { - logger.error("proxy error", err) - }) - return spdyProxy + logger.error("proxy error", err); + }); + return spdyProxy; } protected async handleProxyUpgrade(proxy: httpProxy, req: http.IncomingMessage, socket: net.Socket, head: Buffer) { - const cluster = this.clusterManager.getClusterForRequest(req) + const cluster = this.clusterManager.getClusterForRequest(req); if (cluster) { - const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, "") - const apiUrl = url.parse(cluster.apiUrl) - const pUrl = url.parse(proxyUrl) - const connectOpts = { port: parseInt(pUrl.port), host: pUrl.hostname } - const proxySocket = new net.Socket() + const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, ""); + const apiUrl = url.parse(cluster.apiUrl); + const pUrl = url.parse(proxyUrl); + const connectOpts = { port: parseInt(pUrl.port), host: pUrl.hostname }; + const proxySocket = new net.Socket(); proxySocket.connect(connectOpts, () => { - proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`) - proxySocket.write(`Host: ${apiUrl.host}\r\n`) + proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`); + proxySocket.write(`Host: ${apiUrl.host}\r\n`); for (let i = 0; i < req.rawHeaders.length; i += 2) { - const key = req.rawHeaders[i] + const key = req.rawHeaders[i]; if (key !== "Host" && key !== "Authorization") { - proxySocket.write(`${req.rawHeaders[i]}: ${req.rawHeaders[i+1]}\r\n`) + proxySocket.write(`${req.rawHeaders[i]}: ${req.rawHeaders[i+1]}\r\n`); } } - proxySocket.write("\r\n") - proxySocket.write(head) - }) + proxySocket.write("\r\n"); + proxySocket.write(head); + }); - proxySocket.setKeepAlive(true) - socket.setKeepAlive(true) - proxySocket.setTimeout(0) - socket.setTimeout(0) + proxySocket.setKeepAlive(true); + socket.setKeepAlive(true); + proxySocket.setTimeout(0); + socket.setTimeout(0); proxySocket.on('data', function (chunk) { - socket.write(chunk) - }) + socket.write(chunk); + }); proxySocket.on('end', function () { - socket.end() - }) + socket.end(); + }); proxySocket.on('error', function (err) { socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n"); - socket.end() - }) + socket.end(); + }); socket.on('data', function (chunk) { - proxySocket.write(chunk) - }) + proxySocket.write(chunk); + }); socket.on('end', function () { - proxySocket.end() - }) + proxySocket.end(); + }); socket.on('error', function () { - proxySocket.end() - }) + proxySocket.end(); + }); } } @@ -120,29 +120,29 @@ export class LensProxy { logger.debug("Failed proxy to target: " + JSON.stringify(target, null, 2)); if (req.method === "GET" && (!res.statusCode || res.statusCode >= 500)) { const reqId = this.getRequestId(req); - const retryCount = this.retryCounters.get(reqId) || 0 - const timeoutMs = retryCount * 250 + const retryCount = this.retryCounters.get(reqId) || 0; + const timeoutMs = retryCount * 250; if (retryCount < 20) { - logger.debug(`Retrying proxy request to url: ${reqId}`) + logger.debug(`Retrying proxy request to url: ${reqId}`); setTimeout(() => { - this.retryCounters.set(reqId, retryCount + 1) - this.handleRequest(proxy, req, res) - }, timeoutMs) + this.retryCounters.set(reqId, retryCount + 1); + this.handleRequest(proxy, req, res); + }, timeoutMs); } } } try { - res.writeHead(500).end("Oops, something went wrong.") + res.writeHead(500).end("Oops, something went wrong."); } catch (e) { - logger.error(`[LENS-PROXY]: Failed to write headers: `, e) + logger.error(`[LENS-PROXY]: Failed to write headers: `, e); } - }) + }); return proxy; } protected createWsListener(): WebSocket.Server { - const ws = new WebSocket.Server({ noServer: true }) + const ws = new WebSocket.Server({ noServer: true }); return ws.on("connection", ((socket: WebSocket, req: http.IncomingMessage) => { const cluster = this.clusterManager.getClusterForRequest(req); const nodeParam = url.parse(req.url, true).query["node"]?.toString(); @@ -152,10 +152,10 @@ export class LensProxy { protected async getProxyTarget(req: http.IncomingMessage, contextHandler: ContextHandler): Promise { if (req.url.startsWith(apiKubePrefix)) { - delete req.headers.authorization - req.url = req.url.replace(apiKubePrefix, "") - const isWatchRequest = req.url.includes("watch=") - return await contextHandler.getApiTarget(isWatchRequest) + delete req.headers.authorization; + req.url = req.url.replace(apiKubePrefix, ""); + const isWatchRequest = req.url.includes("watch="); + return await contextHandler.getApiTarget(isWatchRequest); } } @@ -164,9 +164,9 @@ export class LensProxy { } protected async handleRequest(proxy: httpProxy, req: http.IncomingMessage, res: http.ServerResponse) { - const cluster = this.clusterManager.getClusterForRequest(req) + const cluster = this.clusterManager.getClusterForRequest(req); if (cluster) { - const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler) + const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler); if (proxyTarget) { // allow to fetch apis in "clusterId.localhost:port" from "localhost:port" res.setHeader("Access-Control-Allow-Origin", this.origin); diff --git a/src/main/logger.ts b/src/main/logger.ts index f4e2707c27..81d61e8002 100644 --- a/src/main/logger.ts +++ b/src/main/logger.ts @@ -1,13 +1,13 @@ import { app, remote } from "electron"; -import winston from "winston" +import winston from "winston"; import { isDebugging } from "../common/vars"; -const logLevel = process.env.LOG_LEVEL ? process.env.LOG_LEVEL : isDebugging ? "debug" : "info" +const logLevel = process.env.LOG_LEVEL ? process.env.LOG_LEVEL : isDebugging ? "debug" : "info"; const consoleOptions: winston.transports.ConsoleTransportOptions = { handleExceptions: false, level: logLevel, -} +}; const fileOptions: winston.transports.FileTransportOptions = { handleExceptions: false, @@ -17,7 +17,7 @@ const fileOptions: winston.transports.FileTransportOptions = { maxsize: 16 * 1024, maxFiles: 16, tailable: true, -} +}; const logger = winston.createLogger({ format: winston.format.combine( @@ -30,4 +30,4 @@ const logger = winston.createLogger({ ], }); -export default logger +export default logger; diff --git a/src/main/menu.ts b/src/main/menu.ts index 14525581b8..99a0d0bb55 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow, dialog, ipcMain, IpcMainEvent, Menu, MenuItem, MenuItemConstructorOptions, webContents, shell } from "electron" +import { app, BrowserWindow, dialog, ipcMain, IpcMainEvent, Menu, MenuItem, MenuItemConstructorOptions, webContents, shell } from "electron"; import { autorun } from "mobx"; import { WindowManager } from "./window-manager"; import { appName, isMac, isWindows, isTestEnv } from "../common/vars"; @@ -11,7 +11,7 @@ import { menuRegistry } from "../extensions/registries/menu-registry"; import logger from "./logger"; import { exitApp } from "./exit-app"; -export type MenuTopId = "mac" | "file" | "edit" | "view" | "help" +export type MenuTopId = "mac" | "file" | "edit" | "view" | "help"; export function initMenu(windowManager: WindowManager) { return autorun(() => buildMenu(windowManager), { @@ -25,14 +25,14 @@ export function showAbout(browserWindow: BrowserWindow) { `Electron: ${process.versions.electron}`, `Chrome: ${process.versions.chrome}`, `Copyright 2020 Mirantis, Inc.`, - ] + ]; dialog.showMessageBoxSync(browserWindow, { title: `${isWindows ? " ".repeat(2) : ""}${appName}`, type: "info", buttons: ["Close"], message: `Lens`, detail: appInfo.join("\r\n") - }) + }); } export function buildMenu(windowManager: WindowManager) { @@ -44,7 +44,7 @@ export function buildMenu(windowManager: WindowManager) { function activeClusterOnly(menuItems: MenuItemConstructorOptions[]) { if (!windowManager.activeClusterId) { menuItems.forEach(item => { - item.enabled = false + item.enabled = false; }); } return menuItems; @@ -61,7 +61,7 @@ export function buildMenu(windowManager: WindowManager) { { label: "About Lens", click(menuItem: MenuItem, browserWindow: BrowserWindow) { - showAbout(browserWindow) + showAbout(browserWindow); } }, { type: 'separator' }, @@ -69,14 +69,14 @@ export function buildMenu(windowManager: WindowManager) { label: 'Preferences', accelerator: 'CmdOrCtrl+,', click() { - navigate(preferencesURL()) + navigate(preferencesURL()); } }, { label: 'Extensions', accelerator: 'CmdOrCtrl+Shift+E', click() { - navigate(extensionsURL()) + navigate(extensionsURL()); } }, { type: 'separator' }, @@ -90,7 +90,7 @@ export function buildMenu(windowManager: WindowManager) { label: 'Quit', accelerator: 'Cmd+Q', click() { - exitApp() + exitApp(); } } ] @@ -103,7 +103,7 @@ export function buildMenu(windowManager: WindowManager) { label: 'Add Cluster', accelerator: 'CmdOrCtrl+Shift+A', click() { - navigate(addClusterURL()) + navigate(addClusterURL()); } }, ...activeClusterOnly([ @@ -115,7 +115,7 @@ export function buildMenu(windowManager: WindowManager) { params: { clusterId: windowManager.activeClusterId } - })) + })); } } ]), @@ -125,14 +125,14 @@ export function buildMenu(windowManager: WindowManager) { label: 'Preferences', accelerator: 'Ctrl+,', click() { - navigate(preferencesURL()) + navigate(preferencesURL()); } }, { label: 'Extensions', accelerator: 'Ctrl+Shift+E', click() { - navigate(extensionsURL()) + navigate(extensionsURL()); } } ]), @@ -147,7 +147,7 @@ export function buildMenu(windowManager: WindowManager) { label: 'Exit', accelerator: 'Alt+F4', click() { - exitApp() + exitApp(); } } ]) @@ -183,7 +183,7 @@ export function buildMenu(windowManager: WindowManager) { label: 'Forward', accelerator: 'CmdOrCtrl+]', click() { - webContents.getFocusedWebContents()?.goForward() + webContents.getFocusedWebContents()?.goForward(); } }, { @@ -209,7 +209,7 @@ export function buildMenu(windowManager: WindowManager) { { label: "What's new?", click() { - navigate(whatsNewURL()) + navigate(whatsNewURL()); }, }, { @@ -222,7 +222,7 @@ export function buildMenu(windowManager: WindowManager) { { label: "About Lens", click(menuItem: MenuItem, browserWindow: BrowserWindow) { - showAbout(browserWindow) + showAbout(browserWindow); } } ]) @@ -236,7 +236,7 @@ export function buildMenu(windowManager: WindowManager) { edit: editMenu, view: viewMenu, help: helpMenu, - } + }; // Modify menu from extensions-api menuRegistry.getItems().forEach(({ parentId, ...menuItem }) => { @@ -244,12 +244,12 @@ export function buildMenu(windowManager: WindowManager) { const topMenu = appMenu[parentId as MenuTopId].submenu as MenuItemConstructorOptions[]; topMenu.push(menuItem); } catch (err) { - logger.error(`[MENU]: can't register menu item, parentId=${parentId}`, { menuItem }) + logger.error(`[MENU]: can't register menu item, parentId=${parentId}`, { menuItem }); } - }) + }); if (!isMac) { - delete appMenu.mac + delete appMenu.mac; } const menu = Menu.buildFromTemplate(Object.values(appMenu)); @@ -259,9 +259,9 @@ export function buildMenu(windowManager: WindowManager) { // 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[]) => { - let menu: Menu = Menu.getApplicationMenu() + let menu: Menu = Menu.getApplicationMenu(); const parentLabels: string[] = []; - let menuItem: MenuItem + let menuItem: MenuItem; for (const name of names) { parentLabels.push(name); @@ -272,7 +272,7 @@ export function buildMenu(windowManager: WindowManager) { menu = menuItem.submenu; } - const menuPath: string = parentLabels.join(" -> ") + const menuPath: string = parentLabels.join(" -> "); if (!menuItem) { logger.info(`[MENU:test-menu-item-click] Cannot find menu item ${menuPath}`); return; diff --git a/src/main/node-shell-session.ts b/src/main/node-shell-session.ts index 9e97398327..3d48afebc5 100644 --- a/src/main/node-shell-session.ts +++ b/src/main/node-shell-session.ts @@ -1,36 +1,36 @@ -import * as WebSocket from "ws" -import * as pty from "node-pty" +import * as WebSocket from "ws"; +import * as pty from "node-pty"; import { ShellSession } from "./shell-session"; -import { v4 as uuid } from "uuid" -import * as k8s from "@kubernetes/client-node" -import { KubeConfig } from "@kubernetes/client-node" -import { Cluster } from "./cluster" +import { v4 as uuid } from "uuid"; +import * as k8s from "@kubernetes/client-node"; +import { KubeConfig } from "@kubernetes/client-node"; +import { Cluster } from "./cluster"; import logger from "./logger"; -import { appEventBus } from "../common/event-bus" +import { appEventBus } from "../common/event-bus"; export class NodeShellSession extends ShellSession { protected nodeName: string; - protected podId: string - protected kc: KubeConfig + protected podId: string; + protected kc: KubeConfig; constructor(socket: WebSocket, cluster: Cluster, nodeName: string) { - super(socket, cluster) - this.nodeName = nodeName - this.podId = `node-shell-${uuid()}` - this.kc = cluster.getProxyKubeconfig() + super(socket, cluster); + this.nodeName = nodeName; + this.podId = `node-shell-${uuid()}`; + this.kc = cluster.getProxyKubeconfig(); } public async open() { - const shell = await this.kubectl.getPath() - let args = [] + const shell = await this.kubectl.getPath(); + let args = []; if (this.createNodeShellPod(this.podId, this.nodeName)) { await this.waitForRunningPod(this.podId).catch((error) => { - this.exit(1001) - }) + this.exit(1001); + }); } - args = ["exec", "-i", "-t", "-n", "kube-system", this.podId, "--", "sh", "-c", "((clear && bash) || (clear && ash) || (clear && sh))"] + args = ["exec", "-i", "-t", "-n", "kube-system", this.podId, "--", "sh", "-c", "((clear && bash) || (clear && ash) || (clear && sh))"]; - const shellEnv = await this.getCachedShellEnv() + const shellEnv = await this.getCachedShellEnv(); this.shellProcess = pty.spawn(shell, args, { cols: 80, cwd: this.cwd() || shellEnv["HOME"], @@ -39,19 +39,19 @@ export class NodeShellSession extends ShellSession { rows: 30, }); this.running = true; - this.pipeStdout() - this.pipeStdin() - this.closeWebsocketOnProcessExit() - this.exitProcessOnWebsocketClose() + this.pipeStdout(); + this.pipeStdin(); + this.closeWebsocketOnProcessExit(); + this.exitProcessOnWebsocketClose(); - appEventBus.emit({name: "node-shell", action: "open"}) + appEventBus.emit({name: "node-shell", action: "open"}); } protected exit(code = 1000) { if (this.podId) { - this.deleteNodeShellPod() + this.deleteNodeShellPod(); } - super.exit(code) + super.exit(code); } protected async createNodeShellPod(podId: string, nodeName: string) { @@ -86,19 +86,19 @@ export class NodeShellSession extends ShellSession { } } as k8s.V1Pod; await k8sApi.createNamespacedPod("kube-system", pod).catch((error) => { - logger.error(error) - return false - }) - return true + logger.error(error); + return false; + }); + return true; } protected getKubeConfig() { if (this.kc) { - return this.kc + return this.kc; } this.kc = new k8s.KubeConfig(); - this.kc.loadFromFile(this.kubeconfigPath) - return this.kc + this.kc.loadFromFile(this.kubeconfigPath); + return this.kc; } protected waitForRunningPod(podId: string) { @@ -110,36 +110,36 @@ export class NodeShellSession extends ShellSession { // callback is called for each received object. (_type, obj) => { if (obj.metadata.name == podId && obj.status.phase === "Running") { - resolve(true) + resolve(true); } }, // done callback is called if the watch terminates normally (err) => { - logger.error(err) - reject(false) + logger.error(err); + reject(false); } ); setTimeout(() => { req.abort(); reject(false); }, 120 * 1000); - }) + }); } protected deleteNodeShellPod() { const kc = this.getKubeConfig(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); - k8sApi.deleteNamespacedPod(this.podId, "kube-system") + k8sApi.deleteNamespacedPod(this.podId, "kube-system"); } } export async function openShell(socket: WebSocket, cluster: Cluster, nodeName?: string): Promise { let shell: ShellSession; if (nodeName) { - shell = new NodeShellSession(socket, cluster, nodeName) + shell = new NodeShellSession(socket, cluster, nodeName); } else { shell = new ShellSession(socket, cluster); } - shell.open() + shell.open(); return shell; } diff --git a/src/main/port.ts b/src/main/port.ts index b253d3590a..6ba8f71695 100644 --- a/src/main/port.ts +++ b/src/main/port.ts @@ -1,15 +1,15 @@ -import net, { AddressInfo } from "net" -import logger from "./logger" +import net, { AddressInfo } from "net"; +import logger from "./logger"; // todo: check https://github.com/http-party/node-portfinder ? export async function getFreePort(): Promise { logger.debug("Lookup new free port.."); return new Promise((resolve, reject) => { - const server = net.createServer() - server.unref() + const server = net.createServer(); + server.unref(); server.on("listening", () => { - const port = (server.address() as AddressInfo).port + const port = (server.address() as AddressInfo).port; server.close(() => resolve(port)); logger.debug(`New port found: ${port}`); }); @@ -17,6 +17,6 @@ export async function getFreePort(): Promise { logger.error(`Can't resolve new port: "${error}"`); reject(error); }); - server.listen({ host: "127.0.0.1", port: 0 }) - }) + server.listen({ host: "127.0.0.1", port: 0 }); + }); } diff --git a/src/main/port_spec.ts b/src/main/port_spec.ts index c9be25e514..bf01eb5dde 100644 --- a/src/main/port_spec.ts +++ b/src/main/port_spec.ts @@ -1,5 +1,5 @@ -import { EventEmitter } from 'events' -import { getFreePort } from "./port" +import { EventEmitter } from 'events'; +import { getFreePort } from "./port"; let newPort = 0; @@ -8,24 +8,24 @@ jest.mock("net", () => { createServer() { return new class MockServer extends EventEmitter { listen = jest.fn(() => { - this.emit('listening') - return this - }) + this.emit('listening'); + return this; + }); address = () => { - newPort = Math.round(Math.random() * 10000) + newPort = Math.round(Math.random() * 10000); return { port: newPort - } - } - unref = jest.fn() - close = jest.fn(cb => cb()) - } + }; + }; + unref = jest.fn(); + close = jest.fn(cb => cb()); + }; }, - } + }; }); describe("getFreePort", () => { it("finds the next free port", async () => { return expect(getFreePort()).resolves.toEqual(newPort); - }) -}) + }); +}); diff --git a/src/main/prometheus/helm.ts b/src/main/prometheus/helm.ts index f1462931df..56d739c630 100644 --- a/src/main/prometheus/helm.ts +++ b/src/main/prometheus/helm.ts @@ -1,29 +1,29 @@ -import { PrometheusLens } from "./lens" -import { CoreV1Api } from "@kubernetes/client-node" +import { PrometheusLens } from "./lens"; +import { CoreV1Api } from "@kubernetes/client-node"; import { PrometheusService } from "./provider-registry"; -import logger from "../logger" +import logger from "../logger"; export class PrometheusHelm extends PrometheusLens { - id = "helm" - name = "Helm" - rateAccuracy = "5m" + id = "helm"; + name = "Helm"; + rateAccuracy = "5m"; public async getPrometheusService(client: CoreV1Api): Promise { - const labelSelector = "app=prometheus,component=server,heritage=Helm" + const labelSelector = "app=prometheus,component=server,heritage=Helm"; try { - const serviceList = await client.listServiceForAllNamespaces(false, "", null, labelSelector) - const service = serviceList.body.items[0] - if (!service) return + const serviceList = await client.listServiceForAllNamespaces(false, "", null, labelSelector); + const service = serviceList.body.items[0]; + if (!service) return; return { id: this.id, namespace: service.metadata.namespace, service: service.metadata.name, port: service.spec.ports[0].port - } + }; } catch(error) { - logger.warn(`PrometheusHelm: failed to list services: ${error.toString()}`) - return + logger.warn(`PrometheusHelm: failed to list services: ${error.toString()}`); + return; } } } diff --git a/src/main/prometheus/lens.ts b/src/main/prometheus/lens.ts index 4db70bf45d..76a459212d 100644 --- a/src/main/prometheus/lens.ts +++ b/src/main/prometheus/lens.ts @@ -1,24 +1,24 @@ import { PrometheusProvider, PrometheusQueryOpts, PrometheusQuery, PrometheusService } from "./provider-registry"; import { CoreV1Api } from "@kubernetes/client-node"; -import logger from "../logger" +import logger from "../logger"; export class PrometheusLens implements PrometheusProvider { - id = "lens" - name = "Lens" - rateAccuracy = "1m" + id = "lens"; + name = "Lens"; + rateAccuracy = "1m"; public async getPrometheusService(client: CoreV1Api): Promise { try { - const resp = await client.readNamespacedService("prometheus", "lens-metrics") - const service = resp.body + const resp = await client.readNamespacedService("prometheus", "lens-metrics"); + const service = resp.body; return { id: this.id, namespace: service.metadata.namespace, service: service.metadata.name, port: service.spec.ports[0].port - } + }; } catch(error) { - logger.warn(`PrometheusLens: failed to list services: ${error.response.body.message}`) + logger.warn(`PrometheusLens: failed to list services: ${error.response.body.message}`); } } @@ -42,7 +42,7 @@ export class PrometheusLens implements PrometheusProvider { podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`, 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': return { memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_node)`, @@ -51,7 +51,7 @@ export class PrometheusLens implements PrometheusProvider { cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`, 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': return { cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`, @@ -63,21 +63,21 @@ export class PrometheusLens implements PrometheusProvider { fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`, 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': 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': const bytesSent = (ingress: string, statuses: string) => - `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)` + `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`; return { bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"), bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"), requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`, responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)` - } + }; } } } diff --git a/src/main/prometheus/operator.ts b/src/main/prometheus/operator.ts index 3d335ff554..8e27a4a6f3 100644 --- a/src/main/prometheus/operator.ts +++ b/src/main/prometheus/operator.ts @@ -3,30 +3,30 @@ import { CoreV1Api, V1Service } from "@kubernetes/client-node"; import logger from "../logger"; export class PrometheusOperator implements PrometheusProvider { - rateAccuracy = "1m" - id = "operator" - name = "Prometheus Operator" + rateAccuracy = "1m"; + id = "operator"; + name = "Prometheus Operator"; public async getPrometheusService(client: CoreV1Api): Promise { try { - let service: V1Service + let service: V1Service; for (const labelSelector of ["operated-prometheus=true", "self-monitor=true"]) { if (!service) { - const serviceList = await client.listServiceForAllNamespaces(null, null, null, labelSelector) - service = serviceList.body.items[0] + const serviceList = await client.listServiceForAllNamespaces(null, null, null, labelSelector); + service = serviceList.body.items[0]; } } - if (!service) return + if (!service) return; return { id: this.id, namespace: service.metadata.namespace, service: service.metadata.name, port: service.spec.ports[0].port - } + }; } catch(error) { - logger.warn(`PrometheusOperator: failed to list services: ${error.toString()}`) - return + logger.warn(`PrometheusOperator: failed to list services: ${error.toString()}`); + return; } } @@ -50,7 +50,7 @@ export class PrometheusOperator implements PrometheusProvider { podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"})`, 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': 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)`, @@ -59,7 +59,7 @@ export class PrometheusOperator implements PrometheusProvider { cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`, 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': return { cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`, @@ -71,12 +71,12 @@ export class PrometheusOperator implements PrometheusProvider { fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`, 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': 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': const bytesSent = (ingress: string, statuses: string) => `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`; @@ -85,7 +85,7 @@ export class PrometheusOperator implements PrometheusProvider { bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"), requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`, responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)` - } + }; } } } diff --git a/src/main/prometheus/provider-registry.ts b/src/main/prometheus/provider-registry.ts index 0a4eb22e95..641b1b8cf2 100644 --- a/src/main/prometheus/provider-registry.ts +++ b/src/main/prometheus/provider-registry.ts @@ -1,4 +1,4 @@ -import { CoreV1Api } from "@kubernetes/client-node" +import { CoreV1Api } from "@kubernetes/client-node"; export type PrometheusClusterQuery = { memoryUsage: string; @@ -11,7 +11,7 @@ export type PrometheusClusterQuery = { cpuCapacity: string; podUsage: string; podCapacity: string; -} +}; export type PrometheusNodeQuery = { memoryUsage: string; @@ -20,7 +20,7 @@ export type PrometheusNodeQuery = { cpuCapacity: string; fsSize: string; fsUsage: string; -} +}; export type PrometheusPodQuery = { memoryUsage: string; @@ -32,32 +32,32 @@ export type PrometheusPodQuery = { fsUsage: string; networkReceive: string; networkTransmit: string; -} +}; export type PrometheusPvcQuery = { diskUsage: string; diskCapacity: string; -} +}; export type PrometheusIngressQuery = { bytesSentSuccess: string; bytesSentFailure: string; requestDurationSeconds: string; responseDurationSeconds: string; -} +}; export type PrometheusQueryOpts = { [key: string]: string | any; }; -export type PrometheusQuery = PrometheusNodeQuery | PrometheusClusterQuery | PrometheusPodQuery | PrometheusPvcQuery | PrometheusIngressQuery +export type PrometheusQuery = PrometheusNodeQuery | PrometheusClusterQuery | PrometheusPodQuery | PrometheusPvcQuery | PrometheusIngressQuery; export type PrometheusService = { id: string; namespace: string; service: string; port: number; -} +}; export interface PrometheusProvider { id: string; @@ -68,23 +68,23 @@ export interface PrometheusProvider { export type PrometheusProviderList = { [key: string]: PrometheusProvider; -} +}; export class PrometheusProviderRegistry { - private static prometheusProviders: PrometheusProviderList = {} + private static prometheusProviders: PrometheusProviderList = {}; static getProvider(type: string): PrometheusProvider { if (!this.prometheusProviders[type]) { throw "Unknown Prometheus provider"; } - return this.prometheusProviders[type] + return this.prometheusProviders[type]; } static registerProvider(key: string, provider: PrometheusProvider) { - this.prometheusProviders[key] = provider + this.prometheusProviders[key] = provider; } static getProviders(): PrometheusProvider[] { - return Object.values(this.prometheusProviders) + return Object.values(this.prometheusProviders); } } diff --git a/src/main/prometheus/stacklight.ts b/src/main/prometheus/stacklight.ts index 4cb946c81d..35394336d3 100644 --- a/src/main/prometheus/stacklight.ts +++ b/src/main/prometheus/stacklight.ts @@ -1,24 +1,24 @@ import { PrometheusProvider, PrometheusQueryOpts, PrometheusQuery, PrometheusService } from "./provider-registry"; import { CoreV1Api } from "@kubernetes/client-node"; -import logger from "../logger" +import logger from "../logger"; export class PrometheusStacklight implements PrometheusProvider { - id = "stacklight" - name = "Stacklight" - rateAccuracy = "1m" + id = "stacklight"; + name = "Stacklight"; + rateAccuracy = "1m"; public async getPrometheusService(client: CoreV1Api): Promise { try { - const resp = await client.readNamespacedService("prometheus-server", "stacklight") - const service = resp.body + const resp = await client.readNamespacedService("prometheus-server", "stacklight"); + const service = resp.body; return { id: this.id, namespace: service.metadata.namespace, service: service.metadata.name, port: service.spec.ports[0].port - } + }; } catch(error) { - logger.warn(`PrometheusLens: failed to list services: ${error.response.body.message}`) + logger.warn(`PrometheusLens: failed to list services: ${error.response.body.message}`); } } @@ -42,7 +42,7 @@ export class PrometheusStacklight implements PrometheusProvider { podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`, 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': return { memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (node)`, @@ -51,7 +51,7 @@ export class PrometheusStacklight implements PrometheusProvider { cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`, 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': return { cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`, @@ -63,21 +63,21 @@ export class PrometheusStacklight implements PrometheusProvider { fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`, 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': 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': const bytesSent = (ingress: string, statuses: string) => - `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)` + `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`; return { bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"), bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"), requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`, responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)` - } + }; } } } diff --git a/src/main/promise-exec.ts b/src/main/promise-exec.ts index b3bc303165..426bca4c23 100644 --- a/src/main/promise-exec.ts +++ b/src/main/promise-exec.ts @@ -1,4 +1,4 @@ -import * as util from "util" +import * as util from "util"; import { exec } from "child_process"; -export const promiseExec = util.promisify(exec) +export const promiseExec = util.promisify(exec); diff --git a/src/main/proxy-env.ts b/src/main/proxy-env.ts index 04c62ef534..51c8286a7f 100644 --- a/src/main/proxy-env.ts +++ b/src/main/proxy-env.ts @@ -1,18 +1,18 @@ -import { app } from "electron" +import { app } from "electron"; -const switchValue = app.commandLine.getSwitchValue("proxy-server") +const switchValue = app.commandLine.getSwitchValue("proxy-server"); export function mangleProxyEnv() { - let httpsProxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || "" + let httpsProxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || ""; - delete process.env.HTTPS_PROXY - delete process.env.HTTP_PROXY + delete process.env.HTTPS_PROXY; + delete process.env.HTTP_PROXY; if (switchValue !== "") { - httpsProxy = switchValue + httpsProxy = switchValue; } if (httpsProxy !== "") { - process.env.APP_HTTPS_PROXY = httpsProxy + process.env.APP_HTTPS_PROXY = httpsProxy; } } diff --git a/src/main/resource-applier.ts b/src/main/resource-applier.ts index 41441a3f90..0f4647a60f 100644 --- a/src/main/resource-applier.ts +++ b/src/main/resource-applier.ts @@ -1,12 +1,12 @@ import type { Cluster } from "./cluster"; -import { KubernetesObject } from "@kubernetes/client-node" +import { KubernetesObject } from "@kubernetes/client-node"; import { exec } from "child_process"; import fs from "fs"; import * as yaml from "js-yaml"; import path from "path"; import * as tempy from "tempy"; -import logger from "./logger" -import { appEventBus } from "../common/event-bus" +import logger from "./logger"; +import { appEventBus } from "../common/event-bus"; import { cloneJsonObject } from "../common/utils"; export class ResourceApplier { @@ -15,58 +15,58 @@ export class ResourceApplier { async apply(resource: KubernetesObject | any): Promise { resource = this.sanitizeObject(resource); - appEventBus.emit({name: "resource", action: "apply"}) + appEventBus.emit({name: "resource", action: "apply"}); return await this.kubectlApply(yaml.safeDump(resource)); } protected async kubectlApply(content: string): Promise { const { kubeCtl } = this.cluster; - const kubectlPath = await kubeCtl.getPath() + const kubectlPath = await kubeCtl.getPath(); return new Promise((resolve, reject) => { - const fileName = tempy.file({ name: "resource.yaml" }) - fs.writeFileSync(fileName, content) - const cmd = `"${kubectlPath}" apply --kubeconfig "${this.cluster.getProxyKubeconfigPath()}" -o json -f "${fileName}"` + const fileName = tempy.file({ name: "resource.yaml" }); + fs.writeFileSync(fileName, content); + const cmd = `"${kubectlPath}" apply --kubeconfig "${this.cluster.getProxyKubeconfigPath()}" -o json -f "${fileName}"`; logger.debug("shooting manifests with: " + cmd); - const execEnv: NodeJS.ProcessEnv = Object.assign({}, process.env) - const httpsProxy = this.cluster.preferences?.httpsProxy + const execEnv: NodeJS.ProcessEnv = Object.assign({}, process.env); + const httpsProxy = this.cluster.preferences?.httpsProxy; if (httpsProxy) { - execEnv["HTTPS_PROXY"] = httpsProxy + execEnv["HTTPS_PROXY"] = httpsProxy; } exec(cmd, { env: execEnv }, (error, stdout, stderr) => { if (stderr != "") { - fs.unlinkSync(fileName) - reject(stderr) - return + fs.unlinkSync(fileName); + reject(stderr); + return; } - fs.unlinkSync(fileName) - resolve(JSON.parse(stdout)) - }) - }) + fs.unlinkSync(fileName); + resolve(JSON.parse(stdout)); + }); + }); } public async kubectlApplyAll(resources: string[]): Promise { const { kubeCtl } = this.cluster; - const kubectlPath = await kubeCtl.getPath() + const kubectlPath = await kubeCtl.getPath(); return new Promise((resolve, reject) => { - const tmpDir = tempy.directory() + const tmpDir = tempy.directory(); // Dump each resource into tmpDir resources.forEach((resource, index) => { fs.writeFileSync(path.join(tmpDir, `${index}.yaml`), resource); - }) - const cmd = `"${kubectlPath}" apply --kubeconfig "${this.cluster.getProxyKubeconfigPath()}" -o json -f "${tmpDir}"` + }); + const cmd = `"${kubectlPath}" apply --kubeconfig "${this.cluster.getProxyKubeconfigPath()}" -o json -f "${tmpDir}"`; console.log("shooting manifests with:", cmd); exec(cmd, (error, stdout, stderr) => { if (error) { reject("Error applying manifests:" + error); } if (stderr != "") { - reject(stderr) - return + reject(stderr); + return; } - resolve(stdout) - }) - }) + resolve(stdout); + }); + }); } protected sanitizeObject(resource: KubernetesObject | any) { diff --git a/src/main/router.ts b/src/main/router.ts index 230c93f09e..ed072836b9 100644 --- a/src/main/router.ts +++ b/src/main/router.ts @@ -1,12 +1,12 @@ -import Call from "@hapi/call" -import Subtext from "@hapi/subtext" -import http from "http" -import path from "path" -import { readFile } from "fs-extra" -import { Cluster } from "./cluster" +import Call from "@hapi/call"; +import Subtext from "@hapi/subtext"; +import http from "http"; +import path from "path"; +import { readFile } from "fs-extra"; +import { Cluster } from "./cluster"; import { apiPrefix, appName, publicPath, isDevelopment, webpackDevServerPort } from "../common/vars"; import { helmRoute, kubeconfigRoute, metricsRoute, portForwardRoute, resourceApplierRoute, watchRoute } from "./routes"; -import logger from "./logger" +import logger from "./logger"; export interface RouterRequestOpts { req: http.IncomingMessage; @@ -43,25 +43,25 @@ export class Router { public constructor() { this.router = new Call.Router(); - this.addRoutes() + this.addRoutes(); } public async route(cluster: Cluster, req: http.IncomingMessage, res: http.ServerResponse): Promise { const url = new URL(req.url, "http://localhost"); - const path = url.pathname - const method = req.method.toLowerCase() + const path = url.pathname; + const method = req.method.toLowerCase(); const matchingRoute = this.router.route(method, path); const routeFound = !matchingRoute.isBoom; if (routeFound) { const request = await this.getRequest({ req, res, cluster, url, params: matchingRoute.params }); - await matchingRoute.route(request) - return true + await matchingRoute.route(request); + return true; } return false; } protected async getRequest(opts: RouterRequestOpts): Promise { - const { req, res, url, cluster, params } = opts + const { req, res, url, cluster, params } = opts; const { payload } = await Subtext.parse(req, null, { parse: true, output: "data", @@ -76,7 +76,7 @@ export class Router { query: url.searchParams, payload: payload, params: params - } + }; } protected getMimeType(filename: string) { @@ -92,7 +92,7 @@ export class Router { woff2: "font/woff2", ttf: "font/ttf" }; - return mimeTypes[path.extname(filename).slice(1)] || "text/plain" + return mimeTypes[path.extname(filename).slice(1)] || "text/plain"; } async handleStaticFile(filePath: string, res: http.ServerResponse, req: http.IncomingMessage, retryCount = 0) { @@ -114,10 +114,10 @@ export class Router { res.end(); } catch (err) { if (retryCount > 5) { - logger.error("handleStaticFile:", err.toString()) - res.statusCode = 404 - res.end() - return + logger.error("handleStaticFile:", err.toString()); + res.statusCode = 404; + res.end(); + return; } this.handleStaticFile(`${publicPath}/${appName}.html`, res, req, Math.max(retryCount, 0) + 1); } @@ -131,32 +131,32 @@ export class Router { this.handleStaticFile(params.path, response, req); }); - this.router.add({ method: "get", path: `${apiPrefix}/kubeconfig/service-account/{namespace}/{account}` }, kubeconfigRoute.routeServiceAccountRoute.bind(kubeconfigRoute)) + this.router.add({ method: "get", path: `${apiPrefix}/kubeconfig/service-account/{namespace}/{account}` }, kubeconfigRoute.routeServiceAccountRoute.bind(kubeconfigRoute)); // Watch API - this.router.add({ method: "get", path: `${apiPrefix}/watch` }, watchRoute.routeWatch.bind(watchRoute)) + this.router.add({ method: "get", path: `${apiPrefix}/watch` }, watchRoute.routeWatch.bind(watchRoute)); // Metrics API - this.router.add({ method: "post", path: `${apiPrefix}/metrics` }, metricsRoute.routeMetrics.bind(metricsRoute)) + this.router.add({ method: "post", path: `${apiPrefix}/metrics` }, metricsRoute.routeMetrics.bind(metricsRoute)); // Port-forward API - this.router.add({ method: "post", path: `${apiPrefix}/pods/{namespace}/{resourceType}/{resourceName}/port-forward/{port}` }, portForwardRoute.routePortForward.bind(portForwardRoute)) + this.router.add({ method: "post", path: `${apiPrefix}/pods/{namespace}/{resourceType}/{resourceName}/port-forward/{port}` }, portForwardRoute.routePortForward.bind(portForwardRoute)); // Helm API - this.router.add({ method: "get", path: `${apiPrefix}/v2/charts` }, helmRoute.listCharts.bind(helmRoute)) - this.router.add({ method: "get", path: `${apiPrefix}/v2/charts/{repo}/{chart}` }, helmRoute.getChart.bind(helmRoute)) - this.router.add({ method: "get", path: `${apiPrefix}/v2/charts/{repo}/{chart}/values` }, helmRoute.getChartValues.bind(helmRoute)) + this.router.add({ method: "get", path: `${apiPrefix}/v2/charts` }, helmRoute.listCharts.bind(helmRoute)); + this.router.add({ method: "get", path: `${apiPrefix}/v2/charts/{repo}/{chart}` }, helmRoute.getChart.bind(helmRoute)); + this.router.add({ method: "get", path: `${apiPrefix}/v2/charts/{repo}/{chart}/values` }, helmRoute.getChartValues.bind(helmRoute)); - this.router.add({ method: "post", path: `${apiPrefix}/v2/releases` }, helmRoute.installChart.bind(helmRoute)) - this.router.add({ method: `put`, path: `${apiPrefix}/v2/releases/{namespace}/{release}` }, helmRoute.updateRelease.bind(helmRoute)) - this.router.add({ method: `put`, path: `${apiPrefix}/v2/releases/{namespace}/{release}/rollback` }, helmRoute.rollbackRelease.bind(helmRoute)) - this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace?}` }, helmRoute.listReleases.bind(helmRoute)) - this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace}/{release}` }, helmRoute.getRelease.bind(helmRoute)) - this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace}/{release}/values` }, helmRoute.getReleaseValues.bind(helmRoute)) - this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace}/{release}/history` }, helmRoute.getReleaseHistory.bind(helmRoute)) - this.router.add({ method: "delete", path: `${apiPrefix}/v2/releases/{namespace}/{release}` }, helmRoute.deleteRelease.bind(helmRoute)) + this.router.add({ method: "post", path: `${apiPrefix}/v2/releases` }, helmRoute.installChart.bind(helmRoute)); + this.router.add({ method: `put`, path: `${apiPrefix}/v2/releases/{namespace}/{release}` }, helmRoute.updateRelease.bind(helmRoute)); + this.router.add({ method: `put`, path: `${apiPrefix}/v2/releases/{namespace}/{release}/rollback` }, helmRoute.rollbackRelease.bind(helmRoute)); + this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace?}` }, helmRoute.listReleases.bind(helmRoute)); + this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace}/{release}` }, helmRoute.getRelease.bind(helmRoute)); + this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace}/{release}/values` }, helmRoute.getReleaseValues.bind(helmRoute)); + this.router.add({ method: "get", path: `${apiPrefix}/v2/releases/{namespace}/{release}/history` }, helmRoute.getReleaseHistory.bind(helmRoute)); + this.router.add({ method: "delete", path: `${apiPrefix}/v2/releases/{namespace}/{release}` }, helmRoute.deleteRelease.bind(helmRoute)); // Resource Applier API - this.router.add({ method: "post", path: `${apiPrefix}/stack` }, resourceApplierRoute.applyResource.bind(resourceApplierRoute)) + this.router.add({ method: "post", path: `${apiPrefix}/stack` }, resourceApplierRoute.applyResource.bind(resourceApplierRoute)); } } diff --git a/src/main/routes/helm-route.ts b/src/main/routes/helm-route.ts index 0ffd7252d5..853f8ddded 100644 --- a/src/main/routes/helm-route.ts +++ b/src/main/routes/helm-route.ts @@ -1,114 +1,114 @@ -import { LensApiRequest } from "../router" -import { helmService } from "../helm/helm-service" -import { LensApi } from "../lens-api" -import logger from "../logger" +import { LensApiRequest } from "../router"; +import { helmService } from "../helm/helm-service"; +import { LensApi } from "../lens-api"; +import logger from "../logger"; class HelmApiRoute extends LensApi { public async listCharts(request: LensApiRequest) { - const { response } = request - const charts = await helmService.listCharts() - this.respondJson(response, charts) + const { response } = request; + const charts = await helmService.listCharts(); + this.respondJson(response, charts); } public async getChart(request: LensApiRequest) { - const { params, query, response } = request - const chart = await helmService.getChart(params.repo, params.chart, query.get("version")) - this.respondJson(response, chart) + const { params, query, response } = request; + const chart = await helmService.getChart(params.repo, params.chart, query.get("version")); + this.respondJson(response, chart); } public async getChartValues(request: LensApiRequest) { - const { params, query, response } = request - const values = await helmService.getChartValues(params.repo, params.chart, query.get("version")) - this.respondJson(response, values) + const { params, query, response } = request; + const values = await helmService.getChartValues(params.repo, params.chart, query.get("version")); + this.respondJson(response, values); } public async installChart(request: LensApiRequest) { - const { payload, cluster, response } = request + const { payload, cluster, response } = request; try { - const result = await helmService.installChart(cluster, payload) - this.respondJson(response, result, 201) + const result = await helmService.installChart(cluster, payload); + this.respondJson(response, result, 201); } catch (error) { - logger.debug(error) - this.respondText(response, error, 422) + logger.debug(error); + this.respondText(response, error, 422); } } public async updateRelease(request: LensApiRequest) { - const { cluster, params, payload, response } = request + const { cluster, params, payload, response } = request; try { - const result = await helmService.updateRelease(cluster, params.release, params.namespace, payload ) - this.respondJson(response, result) + const result = await helmService.updateRelease(cluster, params.release, params.namespace, payload ); + this.respondJson(response, result); } catch (error) { - logger.debug(error) - this.respondText(response, error, 422) + logger.debug(error); + this.respondText(response, error, 422); } } public async rollbackRelease(request: LensApiRequest) { - const { cluster, params, payload, response } = request + const { cluster, params, payload, response } = request; try { - const result = await helmService.rollback(cluster, params.release, params.namespace, payload.revision) - this.respondJson(response, result) + const result = await helmService.rollback(cluster, params.release, params.namespace, payload.revision); + this.respondJson(response, result); } catch (error) { - logger.debug(error) - this.respondText(response, error) + logger.debug(error); + this.respondText(response, error); } } public async listReleases(request: LensApiRequest) { - const { cluster, params, response } = request + const { cluster, params, response } = request; try { - const result = await helmService.listReleases(cluster, params.namespace) - this.respondJson(response, result) + const result = await helmService.listReleases(cluster, params.namespace); + this.respondJson(response, result); } catch(error) { - logger.debug(error) - this.respondText(response, error) + logger.debug(error); + this.respondText(response, error); } } public async getRelease(request: LensApiRequest) { - const { cluster, params, response } = request + const { cluster, params, response } = request; try { - const result = await helmService.getRelease(cluster, params.release, params.namespace) - this.respondJson(response, result) + const result = await helmService.getRelease(cluster, params.release, params.namespace); + this.respondJson(response, result); } catch (error) { - logger.debug(error) - this.respondText(response, error, 422) + logger.debug(error); + this.respondText(response, error, 422); } } public async getReleaseValues(request: LensApiRequest) { - const { cluster, params, response } = request + const { cluster, params, response } = request; try { - const result = await helmService.getReleaseValues(cluster, params.release, params.namespace) - this.respondText(response, result) + const result = await helmService.getReleaseValues(cluster, params.release, params.namespace); + this.respondText(response, result); } catch (error) { - logger.debug(error) - this.respondText(response, error, 422) + logger.debug(error); + this.respondText(response, error, 422); } } public async getReleaseHistory(request: LensApiRequest) { - const { cluster, params, response } = request + const { cluster, params, response } = request; try { - const result = await helmService.getReleaseHistory(cluster, params.release, params.namespace) - this.respondJson(response, result) + const result = await helmService.getReleaseHistory(cluster, params.release, params.namespace); + this.respondJson(response, result); } catch (error) { - logger.debug(error) - this.respondText(response, error, 422) + logger.debug(error); + this.respondText(response, error, 422); } } public async deleteRelease(request: LensApiRequest) { - const { cluster, params, response } = request + const { cluster, params, response } = request; try { - const result = await helmService.deleteRelease(cluster, params.release, params.namespace) - this.respondJson(response, result) + const result = await helmService.deleteRelease(cluster, params.release, params.namespace); + this.respondJson(response, result); } catch (error) { - logger.debug(error) - this.respondText(response, error, 422) + logger.debug(error); + this.respondText(response, error, 422); } } } -export const helmRoute = new HelmApiRoute() +export const helmRoute = new HelmApiRoute(); diff --git a/src/main/routes/index.ts b/src/main/routes/index.ts index 60a0423de4..5bc5b3f3dd 100644 --- a/src/main/routes/index.ts +++ b/src/main/routes/index.ts @@ -1,6 +1,6 @@ -export * from "./kubeconfig-route" -export * from "./metrics-route" -export * from "./port-forward-route" -export * from "./watch-route" -export * from "./helm-route" -export * from "./resource-applier-route" +export * from "./kubeconfig-route"; +export * from "./metrics-route"; +export * from "./port-forward-route"; +export * from "./watch-route"; +export * from "./helm-route"; +export * from "./resource-applier-route"; diff --git a/src/main/routes/kubeconfig-route.ts b/src/main/routes/kubeconfig-route.ts index 09f1f061cf..1c04b9525d 100644 --- a/src/main/routes/kubeconfig-route.ts +++ b/src/main/routes/kubeconfig-route.ts @@ -1,10 +1,10 @@ -import { LensApiRequest } from "../router" -import { LensApi } from "../lens-api" -import { Cluster } from "../cluster" -import { CoreV1Api, V1Secret } from "@kubernetes/client-node" +import { LensApiRequest } from "../router"; +import { LensApi } from "../lens-api"; +import { Cluster } from "../cluster"; +import { CoreV1Api, V1Secret } from "@kubernetes/client-node"; function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster) { - const tokenData = Buffer.from(secret.data["token"], "base64") + const tokenData = Buffer.from(secret.data["token"], "base64"); return { 'apiVersion': 'v1', 'kind': 'Config', @@ -36,23 +36,23 @@ function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster } ], 'current-context': cluster.contextName - } + }; } class KubeconfigRoute extends LensApi { public async routeServiceAccountRoute(request: LensApiRequest) { - const { params, response, cluster} = request + const { params, response, cluster} = request; const client = cluster.getProxyKubeconfig().makeApiClient(CoreV1Api); - const secretList = await client.listNamespacedSecret(params.namespace) + const secretList = await client.listNamespacedSecret(params.namespace); const secret = secretList.body.items.find(secret => { const { annotations } = secret.metadata; return annotations && annotations["kubernetes.io/service-account.name"] == params.account; }); const data = generateKubeConfig(params.account, secret, cluster); - this.respondJson(response, data) + this.respondJson(response, data); } } -export const kubeconfigRoute = new KubeconfigRoute() +export const kubeconfigRoute = new KubeconfigRoute(); diff --git a/src/main/routes/metrics-route.ts b/src/main/routes/metrics-route.ts index dc77f7fb9f..254abe188f 100644 --- a/src/main/routes/metrics-route.ts +++ b/src/main/routes/metrics-route.ts @@ -1,32 +1,32 @@ -import { LensApiRequest } from "../router" -import { LensApi } from "../lens-api" -import { Cluster } from "../cluster" -import _ from "lodash" +import { LensApiRequest } from "../router"; +import { LensApi } from "../lens-api"; +import { Cluster } from "../cluster"; +import _ from "lodash"; export type IMetricsQuery = string | string[] | { [metricName: string]: string; -} +}; // This is used for backoff retry tracking. -const MAX_ATTEMPTS = 5 -const ATTEMPTS = [...(_.fill(Array(MAX_ATTEMPTS - 1), false)), true] +const MAX_ATTEMPTS = 5; +const ATTEMPTS = [...(_.fill(Array(MAX_ATTEMPTS - 1), false)), true]; // prometheus metrics loader async function loadMetrics(promQueries: string[], cluster: Cluster, prometheusPath: string, queryParams: Record): Promise { - const queries = promQueries.map(p => p.trim()) - const loaders = new Map>() + const queries = promQueries.map(p => p.trim()); + const loaders = new Map>(); async function loadMetric(query: string): Promise { async function loadMetricHelper(): Promise { for (const [attempt, lastAttempt] of ATTEMPTS.entries()) { // retry try { - return await cluster.getMetrics(prometheusPath, { query, ...queryParams }) + return await cluster.getMetrics(prometheusPath, { query, ...queryParams }); } catch (error) { if (lastAttempt || error?.statusCode === 404) { return { status: error.toString(), data: { result: [] }, - } + }; } await new Promise(resolve => setTimeout(resolve, (attempt + 1) * 1000)); // add delay before repeating request @@ -34,41 +34,41 @@ async function loadMetrics(promQueries: string[], cluster: Cluster, prometheusPa } } - return loaders.get(query) ?? loaders.set(query, loadMetricHelper()).get(query) + return loaders.get(query) ?? loaders.set(query, loadMetricHelper()).get(query); } - return Promise.all(queries.map(loadMetric)) + return Promise.all(queries.map(loadMetric)); } class MetricsRoute extends LensApi { async routeMetrics({ response, cluster, payload, query }: LensApiRequest) { - const queryParams: IMetricsQuery = Object.fromEntries(query.entries()) + const queryParams: IMetricsQuery = Object.fromEntries(query.entries()); try { const [prometheusPath, prometheusProvider] = await Promise.all([ cluster.contextHandler.getPrometheusPath(), cluster.contextHandler.getPrometheusProvider() - ]) + ]); // return data in same structure as query if (typeof payload === "string") { - const [data] = await loadMetrics([payload], cluster, prometheusPath, queryParams) - this.respondJson(response, data) + const [data] = await loadMetrics([payload], cluster, prometheusPath, queryParams); + this.respondJson(response, data); } else if (Array.isArray(payload)) { - const data = await loadMetrics(payload, cluster, prometheusPath, queryParams) - this.respondJson(response, data) + const data = await loadMetrics(payload, cluster, prometheusPath, queryParams); + this.respondJson(response, data); } else { const queries = Object.entries(payload).map(([queryName, queryOpts]) => ( (prometheusProvider.getQueries(queryOpts) as Record)[queryName] - )) - const result = await loadMetrics(queries, cluster, prometheusPath, queryParams) - const data = Object.fromEntries(Object.keys(payload).map((metricName, i) => [metricName, result[i]])) - this.respondJson(response, data) + )); + const result = await loadMetrics(queries, cluster, prometheusPath, queryParams); + const data = Object.fromEntries(Object.keys(payload).map((metricName, i) => [metricName, result[i]])); + this.respondJson(response, data); } } catch { - this.respondJson(response, {}) + this.respondJson(response, {}); } } } -export const metricsRoute = new MetricsRoute() +export const metricsRoute = new MetricsRoute(); diff --git a/src/main/routes/port-forward-route.ts b/src/main/routes/port-forward-route.ts index 7ed79aa936..55402ff72f 100644 --- a/src/main/routes/port-forward-route.ts +++ b/src/main/routes/port-forward-route.ts @@ -1,14 +1,14 @@ -import { LensApiRequest } from "../router" -import { LensApi } from "../lens-api" -import { spawn, ChildProcessWithoutNullStreams } from "child_process" -import { Kubectl } from "../kubectl" -import { getFreePort } from "../port" -import { shell } from "electron" -import * as tcpPortUsed from "tcp-port-used" -import logger from "../logger" +import { LensApiRequest } from "../router"; +import { LensApi } from "../lens-api"; +import { spawn, ChildProcessWithoutNullStreams } from "child_process"; +import { Kubectl } from "../kubectl"; +import { getFreePort } from "../port"; +import { shell } from "electron"; +import * as tcpPortUsed from "tcp-port-used"; +import logger from "../logger"; class PortForward { - public static portForwards: PortForward[] = [] + public static portForwards: PortForward[] = []; static getPortforward(forward: {clusterId: string; kind: string; name: string; namespace: string; port: string}) { return PortForward.portForwards.find((pf) => { @@ -18,70 +18,70 @@ class PortForward { pf.name == forward.name && pf.namespace == forward.namespace && pf.port == forward.port - ) - }) + ); + }); } - public clusterId: string - public process: ChildProcessWithoutNullStreams - public kubeConfig: string - public kind: string - public namespace: string - public name: string - public port: string - public localPort: number + public clusterId: string; + public process: ChildProcessWithoutNullStreams; + public kubeConfig: string; + public kind: string; + public namespace: string; + public name: string; + public port: string; + public localPort: number; constructor(obj: any) { - Object.assign(this, obj) + Object.assign(this, obj); } public async start() { - this.localPort = await getFreePort() - const kubectlBin = await Kubectl.bundled().getPath() + this.localPort = await getFreePort(); + const kubectlBin = await Kubectl.bundled().getPath(); const args = [ "--kubeconfig", this.kubeConfig, "port-forward", "-n", this.namespace, `${this.kind}/${this.name}`, `${this.localPort}:${this.port}` - ] + ]; this.process = spawn(kubectlBin, args, { env: process.env - }) - PortForward.portForwards.push(this) + }); + PortForward.portForwards.push(this); this.process.on("exit", () => { - const index = PortForward.portForwards.indexOf(this) + const index = PortForward.portForwards.indexOf(this); if (index > -1) { - PortForward.portForwards.splice(index, 1) + PortForward.portForwards.splice(index, 1); } - }) + }); try { - await tcpPortUsed.waitUntilUsed(this.localPort, 500, 15000) - return true + await tcpPortUsed.waitUntilUsed(this.localPort, 500, 15000); + return true; } catch (error) { - this.process.kill() - return false + this.process.kill(); + return false; } } public open() { - shell.openExternal(`http://localhost:${this.localPort}`) + shell.openExternal(`http://localhost:${this.localPort}`); } } class PortForwardRoute extends LensApi { public async routePortForward(request: LensApiRequest) { - const { params, response, cluster} = request - const { namespace, port, resourceType, resourceName } = params + const { params, response, cluster} = request; + const { namespace, port, resourceType, resourceName } = params; let portForward = PortForward.getPortforward({ clusterId: cluster.id, kind: resourceType, name: resourceName, namespace: namespace, port: port - }) + }); if (!portForward) { - logger.info(`Creating a new port-forward ${namespace}/${resourceType}/${resourceName}:${port}`) + logger.info(`Creating a new port-forward ${namespace}/${resourceType}/${resourceName}:${port}`); portForward = new PortForward({ clusterId: cluster.id, kind: resourceType, @@ -89,20 +89,20 @@ class PortForwardRoute extends LensApi { name: resourceName, port: port, kubeConfig: cluster.getProxyKubeconfigPath() - }) - const started = await portForward.start() + }); + const started = await portForward.start(); if (!started) { this.respondJson(response, { message: "Failed to open port-forward" - }, 400) - return + }, 400); + return; } } - portForward.open() + portForward.open(); - this.respondJson(response, {}) + this.respondJson(response, {}); } } -export const portForwardRoute = new PortForwardRoute() +export const portForwardRoute = new PortForwardRoute(); diff --git a/src/main/routes/resource-applier-route.ts b/src/main/routes/resource-applier-route.ts index 56125af8f3..8bbfec0d9c 100644 --- a/src/main/routes/resource-applier-route.ts +++ b/src/main/routes/resource-applier-route.ts @@ -1,17 +1,17 @@ -import { LensApiRequest } from "../router" -import { LensApi } from "../lens-api" -import { ResourceApplier } from "../resource-applier" +import { LensApiRequest } from "../router"; +import { LensApi } from "../lens-api"; +import { ResourceApplier } from "../resource-applier"; class ResourceApplierApiRoute extends LensApi { public async applyResource(request: LensApiRequest) { - const { response, cluster, payload } = request + const { response, cluster, payload } = request; try { const resource = await new ResourceApplier(cluster).apply(payload); - this.respondJson(response, [resource], 200) + this.respondJson(response, [resource], 200); } catch (error) { - this.respondText(response, error, 422) + this.respondText(response, error, 422); } } } -export const resourceApplierRoute = new ResourceApplierApiRoute() +export const resourceApplierRoute = new ResourceApplierApiRoute(); diff --git a/src/main/routes/watch-route.ts b/src/main/routes/watch-route.ts index d88276eaac..dd42460a9d 100644 --- a/src/main/routes/watch-route.ts +++ b/src/main/routes/watch-route.ts @@ -1,53 +1,53 @@ -import { LensApiRequest } from "../router" -import { LensApi } from "../lens-api" -import { Watch, KubeConfig } from "@kubernetes/client-node" -import { ServerResponse } from "http" -import { Request } from "request" -import logger from "../logger" +import { LensApiRequest } from "../router"; +import { LensApi } from "../lens-api"; +import { Watch, KubeConfig } from "@kubernetes/client-node"; +import { ServerResponse } from "http"; +import { Request } from "request"; +import logger from "../logger"; class ApiWatcher { - private apiUrl: string - private response: ServerResponse - private watchRequest: Request - private watch: Watch - private processor: NodeJS.Timeout - private eventBuffer: any[] = [] + private apiUrl: string; + private response: ServerResponse; + private watchRequest: Request; + private watch: Watch; + private processor: NodeJS.Timeout; + private eventBuffer: any[] = []; constructor(apiUrl: string, kubeConfig: KubeConfig, response: ServerResponse) { - this.apiUrl = apiUrl - this.watch = new Watch(kubeConfig) - this.response = response + this.apiUrl = apiUrl; + this.watch = new Watch(kubeConfig); + this.response = response; } public async start() { if (this.processor) { - clearInterval(this.processor) + clearInterval(this.processor); } this.processor = setInterval(() => { - const events = this.eventBuffer.splice(0) - events.map(event => this.sendEvent(event)) - this.response.flushHeaders() - }, 50) - this.watchRequest = await this.watch.watch(this.apiUrl, {}, this.watchHandler.bind(this), this.doneHandler.bind(this)) + const events = this.eventBuffer.splice(0); + events.map(event => this.sendEvent(event)); + this.response.flushHeaders(); + }, 50); + this.watchRequest = await this.watch.watch(this.apiUrl, {}, this.watchHandler.bind(this), this.doneHandler.bind(this)); } public stop() { - if (!this.watchRequest) { return } + if (!this.watchRequest) { return; } if (this.processor) { - clearInterval(this.processor) + clearInterval(this.processor); } - logger.debug("Stopping watcher for api: " + this.apiUrl) + logger.debug("Stopping watcher for api: " + this.apiUrl); try { - this.watchRequest.abort() + this.watchRequest.abort(); this.sendEvent({ type: "STREAM_END", url: this.apiUrl, status: 410, - }) - logger.debug("watch aborted") + }); + logger.debug("watch aborted"); } catch (error) { - logger.error("Watch abort errored:" + error) + logger.error("Watch abort errored:" + error); } } @@ -55,12 +55,12 @@ class ApiWatcher { this.eventBuffer.push({ type: phase, object: obj - }) + }); } private doneHandler(error: Error) { - if (error) logger.warn("watch ended: " + error.toString()) - this.watchRequest.abort() + if (error) logger.warn("watch ended: " + error.toString()); + this.watchRequest.abort(); } private sendEvent(evt: any) { @@ -72,40 +72,40 @@ class ApiWatcher { class WatchRoute extends LensApi { public async routeWatch(request: LensApiRequest) { - const { params, response, cluster} = request - const apis: string[] = request.query.getAll("api") - const watchers: ApiWatcher[] = [] + const { params, response, cluster} = request; + const apis: string[] = request.query.getAll("api"); + const watchers: ApiWatcher[] = []; if (!apis.length) { this.respondJson(response, { message: "Empty request. Query params 'api' are not provided.", example: "?api=/api/v1/pods&api=/api/v1/nodes", - }, 400) - return + }, 400); + return; } - response.setHeader("Content-Type", "text/event-stream") - response.setHeader("Cache-Control", "no-cache") - response.setHeader("Connection", "keep-alive") - logger.debug("watch using kubeconfig:" + JSON.stringify(cluster.getProxyKubeconfig(), null, 2)) + response.setHeader("Content-Type", "text/event-stream"); + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Connection", "keep-alive"); + logger.debug("watch using kubeconfig:" + JSON.stringify(cluster.getProxyKubeconfig(), null, 2)); apis.forEach(apiUrl => { - const watcher = new ApiWatcher(apiUrl, cluster.getProxyKubeconfig(), response) - watcher.start() - watchers.push(watcher) - }) + const watcher = new ApiWatcher(apiUrl, cluster.getProxyKubeconfig(), response); + watcher.start(); + watchers.push(watcher); + }); request.raw.req.on("close", () => { - logger.debug("Watch request closed") - watchers.map(watcher => watcher.stop()) - }) + logger.debug("Watch request closed"); + watchers.map(watcher => watcher.stop()); + }); request.raw.req.on("end", () => { - logger.debug("Watch request ended") - watchers.map(watcher => watcher.stop()) - }) + logger.debug("Watch request ended"); + watchers.map(watcher => watcher.stop()); + }); } } -export const watchRoute = new WatchRoute() +export const watchRoute = new WatchRoute(); diff --git a/src/main/shell-session.ts b/src/main/shell-session.ts index 6ea9e4eede..42e0039047 100644 --- a/src/main/shell-session.ts +++ b/src/main/shell-session.ts @@ -1,23 +1,23 @@ -import * as pty from "node-pty" -import * as WebSocket from "ws" +import * as pty from "node-pty"; +import * as WebSocket from "ws"; import { EventEmitter } from "events"; -import path from "path" -import shellEnv from "shell-env" -import { app } from "electron" -import { Kubectl } from "./kubectl" -import { Cluster } from "./cluster" +import path from "path"; +import shellEnv from "shell-env"; +import { app } from "electron"; +import { Kubectl } from "./kubectl"; +import { Cluster } from "./cluster"; import { ClusterPreferences } from "../common/cluster-store"; -import { helmCli } from "./helm/helm-cli" +import { helmCli } from "./helm/helm-cli"; import { isWindows } from "../common/vars"; -import { appEventBus } from "../common/event-bus" +import { appEventBus } from "../common/event-bus"; import { userStore } from "../common/user-store"; export class ShellSession extends EventEmitter { - static shellEnvs: Map = new Map() + static shellEnvs: Map = new Map(); - protected websocket: WebSocket - protected shellProcess: pty.IPty - protected kubeconfigPath: string + protected websocket: WebSocket; + protected shellProcess: pty.IPty; + protected kubeconfigPath: string; protected nodeShellPod: string; protected kubectl: Kubectl; protected kubectlBinDir: string; @@ -28,22 +28,22 @@ export class ShellSession extends EventEmitter { protected clusterId: string; constructor(socket: WebSocket, cluster: Cluster) { - super() - this.websocket = socket - this.kubeconfigPath = cluster.getProxyKubeconfigPath() - this.kubectl = new Kubectl(cluster.version) - this.preferences = cluster.preferences || {} - this.clusterId = cluster.id + super(); + this.websocket = socket; + this.kubeconfigPath = cluster.getProxyKubeconfigPath(); + this.kubectl = new Kubectl(cluster.version); + this.preferences = cluster.preferences || {}; + this.clusterId = cluster.id; } public async open() { - this.kubectlBinDir = await this.kubectl.binDir() - const pathFromPreferences = userStore.preferences.kubectlBinariesPath || this.kubectl.getBundledPath() - this.kubectlPathDir = userStore.preferences.downloadKubectlBinaries ? this.kubectlBinDir : path.dirname(pathFromPreferences) - this.helmBinDir = helmCli.getBinaryDir() - const env = await this.getCachedShellEnv() - const shell = env.PTYSHELL - const args = await this.getShellArgs(shell) + this.kubectlBinDir = await this.kubectl.binDir(); + const pathFromPreferences = userStore.preferences.kubectlBinariesPath || this.kubectl.getBundledPath(); + this.kubectlPathDir = userStore.preferences.downloadKubectlBinaries ? this.kubectlBinDir : path.dirname(pathFromPreferences); + this.helmBinDir = helmCli.getBinaryDir(); + const env = await this.getCachedShellEnv(); + const shell = env.PTYSHELL; + const args = await this.getShellArgs(shell); this.shellProcess = pty.spawn(shell, args, { cols: 80, cwd: this.cwd() || env.HOME, @@ -53,138 +53,138 @@ export class ShellSession extends EventEmitter { }); this.running = true; - this.pipeStdout() - this.pipeStdin() - this.closeWebsocketOnProcessExit() - this.exitProcessOnWebsocketClose() + this.pipeStdout(); + this.pipeStdin(); + this.closeWebsocketOnProcessExit(); + this.exitProcessOnWebsocketClose(); - appEventBus.emit({name: "shell", action: "open"}) + appEventBus.emit({name: "shell", action: "open"}); } protected cwd(): string { if(!this.preferences || !this.preferences.terminalCWD || this.preferences.terminalCWD === "") { - return null + return null; } - return this.preferences.terminalCWD + return this.preferences.terminalCWD; } protected async getShellArgs(shell: string): Promise> { switch(path.basename(shell)) { case "powershell.exe": - return ["-NoExit", "-command", `& {Set-Location $Env:USERPROFILE; $Env:PATH="${this.helmBinDir};${this.kubectlPathDir};$Env:PATH"}`] + 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}"`] + return ["--login", "--init-command", `export PATH="${this.helmBinDir}:${this.kubectlPathDir}:$PATH"; export KUBECONFIG="${this.kubeconfigPath}"`]; case "zsh": - return ["--login"] + return ["--login"]; default: - return [] + return []; } } protected async getCachedShellEnv() { - let env = ShellSession.shellEnvs.get(this.clusterId) + let env = ShellSession.shellEnvs.get(this.clusterId); if (!env) { - env = await this.getShellEnv() - ShellSession.shellEnvs.set(this.clusterId, env) + env = await this.getShellEnv(); + ShellSession.shellEnvs.set(this.clusterId, env); } else { // refresh env in the background this.getShellEnv().then((shellEnv: any) => { - ShellSession.shellEnvs.set(this.clusterId, shellEnv) - }) + ShellSession.shellEnvs.set(this.clusterId, shellEnv); + }); } - return env + return env; } protected async getShellEnv() { - const env = JSON.parse(JSON.stringify(await shellEnv())) - const pathStr = [this.kubectlBinDir, this.helmBinDir, process.env.PATH].join(path.delimiter) + const env = JSON.parse(JSON.stringify(await shellEnv())); + const pathStr = [this.kubectlBinDir, this.helmBinDir, process.env.PATH].join(path.delimiter); if(isWindows) { - env["SystemRoot"] = process.env.SystemRoot - env["PTYSHELL"] = "powershell.exe" - env["PATH"] = pathStr + env["SystemRoot"] = process.env.SystemRoot; + env["PTYSHELL"] = "powershell.exe"; + env["PATH"] = pathStr; } else if(typeof(process.env.SHELL) != "undefined") { - env["PTYSHELL"] = process.env.SHELL - env["PATH"] = pathStr + env["PTYSHELL"] = process.env.SHELL; + env["PATH"] = pathStr; } else { - env["PTYSHELL"] = "" // blank runs the system default shell + env["PTYSHELL"] = ""; // blank runs the system default shell } if(path.basename(env["PTYSHELL"]) === "zsh") { - env["OLD_ZDOTDIR"] = env.ZDOTDIR || env.HOME - env["ZDOTDIR"] = this.kubectlBinDir + env["OLD_ZDOTDIR"] = env.ZDOTDIR || env.HOME; + env["ZDOTDIR"] = this.kubectlBinDir; } - env["PTYPID"] = process.pid.toString() - env["KUBECONFIG"] = this.kubeconfigPath - env["TERM_PROGRAM"] = app.getName() - env["TERM_PROGRAM_VERSION"] = app.getVersion() + env["PTYPID"] = process.pid.toString(); + env["KUBECONFIG"] = this.kubeconfigPath; + env["TERM_PROGRAM"] = app.getName(); + env["TERM_PROGRAM_VERSION"] = app.getVersion(); if (this.preferences.httpsProxy) { - env["HTTPS_PROXY"] = this.preferences.httpsProxy + env["HTTPS_PROXY"] = this.preferences.httpsProxy; } - const no_proxy = ["localhost", "127.0.0.1", env["NO_PROXY"]] - env["NO_PROXY"] = no_proxy.filter(address => !!address).join() + const no_proxy = ["localhost", "127.0.0.1", env["NO_PROXY"]]; + env["NO_PROXY"] = no_proxy.filter(address => !!address).join(); if (env.DEBUG) { // do not pass debug option to bash - delete env["DEBUG"] + delete env["DEBUG"]; } - return(env) + return(env); } protected pipeStdout() { // send shell output to websocket this.shellProcess.onData(((data: string) => { - this.sendResponse(data) + this.sendResponse(data); })); } protected pipeStdin() { // write websocket messages to shellProcess this.websocket.on("message", (data: string) => { - if (!this.running) { return } + if (!this.running) { return; } - const message = Buffer.from(data.slice(1, data.length), "base64").toString() + const message = Buffer.from(data.slice(1, data.length), "base64").toString(); switch (data[0]) { case "0": - this.shellProcess.write(message) + this.shellProcess.write(message); break; case "4": - const resizeMsgObj = JSON.parse(message) - this.shellProcess.resize(resizeMsgObj["Width"], resizeMsgObj["Height"]) + const resizeMsgObj = JSON.parse(message); + this.shellProcess.resize(resizeMsgObj["Width"], resizeMsgObj["Height"]); break; case "9": - this.emit('newToken', message) + this.emit('newToken', message); break; } - }) + }); } protected exit(code = 1000) { - if (this.websocket.readyState == this.websocket.OPEN) this.websocket.close(code) - this.emit('exit') + if (this.websocket.readyState == this.websocket.OPEN) this.websocket.close(code); + this.emit('exit'); } protected closeWebsocketOnProcessExit() { this.shellProcess.onExit(({ exitCode }) => { - this.running = false - let timeout = 0 + this.running = false; + let timeout = 0; if (exitCode > 0) { - this.sendResponse("Terminal will auto-close in 15 seconds ...") - timeout = 15*1000 + this.sendResponse("Terminal will auto-close in 15 seconds ..."); + timeout = 15*1000; } setTimeout(() => { - this.exit() - }, timeout) + this.exit(); + }, timeout); }); } protected exitProcessOnWebsocketClose() { this.websocket.on("close", () => { - this.killShellProcess() - }) + this.killShellProcess(); + }); } protected killShellProcess(){ @@ -192,17 +192,17 @@ export class ShellSession extends EventEmitter { // On Windows we need to kill the shell process by pid, since Lens won't respond after a while if using `this.shellProcess.kill()` if (isWindows) { try { - process.kill(this.shellProcess.pid) + process.kill(this.shellProcess.pid); } catch(e) { - return + return; } } else { - this.shellProcess.kill() + this.shellProcess.kill(); } } } protected sendResponse(msg: string) { - this.websocket.send("1" + Buffer.from(msg).toString("base64")) + this.websocket.send("1" + Buffer.from(msg).toString("base64")); } } diff --git a/src/main/shell-sync.ts b/src/main/shell-sync.ts index 373d0a36ba..46d5788c12 100644 --- a/src/main/shell-sync.ts +++ b/src/main/shell-sync.ts @@ -1,4 +1,4 @@ -import shellEnv from "shell-env" +import shellEnv from "shell-env"; import os from "os"; import { app } from "electron"; import logger from "./logger"; @@ -19,7 +19,7 @@ export async function shellSync() { try { envVars = await shellEnv(shell); } catch (error) { - logger.error(`shellEnv: ${error}`) + logger.error(`shellEnv: ${error}`); } const env: Env = JSON.parse(JSON.stringify(envVars)); @@ -27,12 +27,12 @@ export async function shellSync() { // the LANG env var expects an underscore instead of electron's dash env.LANG = `${app.getLocale().replace('-', '_')}.UTF-8`; } else if (!env.LANG.endsWith(".UTF-8")) { - env.LANG += ".UTF-8" + env.LANG += ".UTF-8"; } // Overwrite PATH on darwin if (process.env.NODE_ENV === "production" && process.platform === "darwin") { - process.env["PATH"] = env.PATH + process.env["PATH"] = env.PATH; } // The spread operator allows joining of objects. The precedence is last to first. diff --git a/src/main/tray.ts b/src/main/tray.ts index 268e006089..f84ea21896 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -1,6 +1,6 @@ -import path from "path" -import packageInfo from "../../package.json" -import { dialog, Menu, NativeImage, nativeTheme, Tray } from "electron" +import path from "path"; +import packageInfo from "../../package.json"; +import { dialog, Menu, NativeImage, nativeTheme, Tray } from "electron"; import { autorun } from "mobx"; import { showAbout } from "./menu"; import { AppUpdater } from "./app-updater"; @@ -24,7 +24,7 @@ export function getTrayIcon(isDark = nativeTheme.shouldUseDarkColors): string { __static, isDevelopment ? "../build/tray" : "icons", // copied within electron-builder extras `tray_icon${isDark ? "_dark" : ""}.png` - ) + ); } export function initTray(windowManager: WindowManager) { @@ -35,18 +35,18 @@ export function initTray(windowManager: WindowManager) { } catch (err) { logger.error(`[TRAY]: building failed: ${err}`); } - }) + }); return () => { dispose(); tray?.destroy(); tray = null; - } + }; } export function buildTray(icon: string | NativeImage, menu: Menu) { if (!tray) { - tray = new Tray(icon) - tray.setToolTip(packageInfo.description) + tray = new Tray(icon); + tray.setToolTip(packageInfo.description); tray.setIgnoreDoubleClickEvents(true); } @@ -70,7 +70,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu { { label: "Open Lens", async click() { - await windowManager.ensureMainWindow() + await windowManager.ensureMainWindow(); }, }, { @@ -98,9 +98,9 @@ export function createTrayMenu(windowManager: WindowManager): Menu { clusterStore.setActive(clusterId); windowManager.navigate(clusterViewURL({ params: { clusterId } })); } - } + }; }) - } + }; }), }, { @@ -112,7 +112,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu { dialog.showMessageBoxSync(browserWindow, { message: "No updates available", type: "info", - }) + }); } }, }, @@ -120,7 +120,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu { { label: 'Quit App', click() { - exitApp() + exitApp(); } } ]); diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index 019ed270eb..00fbdd4243 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -1,9 +1,9 @@ import type { ClusterId } from "../common/cluster-store"; import { observable } from "mobx"; -import { app, BrowserWindow, dialog, shell, webContents } from "electron" -import windowStateKeeper from "electron-window-state" -import { appEventBus } from "../common/event-bus" -import { subscribeToBroadcast } from "../common/ipc" +import { app, BrowserWindow, dialog, shell, webContents } from "electron"; +import windowStateKeeper from "electron-window-state"; +import { appEventBus } from "../common/event-bus"; +import { subscribeToBroadcast } from "../common/ipc"; import { initMenu } from "./menu"; import { initTray } from "./tray"; import { Singleton } from "../common/utils"; @@ -26,7 +26,7 @@ export class WindowManager extends Singleton { } get mainUrl() { - return `http://localhost:${this.proxyPort}` + return `http://localhost:${this.proxyPort}`; } async initMainWindow(showSplash = true) { @@ -63,14 +63,14 @@ export class WindowManager extends Singleton { shell.openExternal(url); }); this.mainWindow.webContents.on("dom-ready", () => { - appEventBus.emit({name: "app", action: "dom-ready"}) - }) + appEventBus.emit({name: "app", action: "dom-ready"}); + }); this.mainWindow.on("focus", () => { - appEventBus.emit({name: "app", action: "focus"}) - }) + appEventBus.emit({name: "app", action: "focus"}); + }); this.mainWindow.on("blur", () => { - appEventBus.emit({name: "app", action: "blur"}) - }) + appEventBus.emit({name: "app", action: "blur"}); + }); // clean up this.mainWindow.on("closed", () => { @@ -78,16 +78,16 @@ export class WindowManager extends Singleton { this.mainWindow = null; this.splashWindow = null; app.dock?.hide(); // hide icon in dock (mac-os) - }) + }); } try { if (showSplash) await this.showSplash(); await this.mainWindow.loadURL(this.mainUrl); this.mainWindow.show(); this.splashWindow?.close(); - appEventBus.emit({ name: "app", action: "start" }) + appEventBus.emit({ name: "app", action: "start" }); } catch (err) { - dialog.showErrorBox("ERROR!", err.toString()) + dialog.showErrorBox("ERROR!", err.toString()); } } @@ -103,7 +103,7 @@ export class WindowManager extends Singleton { // track visible cluster from ui subscribeToBroadcast("cluster-view:current-id", (event, clusterId: ClusterId) => { this.activeClusterId = clusterId; - }) + }); } async ensureMainWindow(): Promise { @@ -126,11 +126,11 @@ export class WindowManager extends Singleton { channel: "renderer:navigate", frameId: frameId, data: [url], - }) + }); } reload() { - const frameId = clusterFrameMap.get(this.activeClusterId) + const frameId = clusterFrameMap.get(this.activeClusterId); if (frameId) { this.sendToView({ channel: "renderer:reload", frameId }); } else { @@ -169,7 +169,7 @@ export class WindowManager extends Singleton { this.splashWindow = null; Object.entries(this.disposers).forEach(([name, dispose]) => { dispose(); - delete this.disposers[name] + delete this.disposers[name]; }); } } diff --git a/src/migrations/cluster-store/2.0.0-beta.2.ts b/src/migrations/cluster-store/2.0.0-beta.2.ts index 8a01af5407..245e9c019c 100644 --- a/src/migrations/cluster-store/2.0.0-beta.2.ts +++ b/src/migrations/cluster-store/2.0.0-beta.2.ts @@ -13,4 +13,4 @@ export default migration({ store.set(contextName, { kubeConfig: value[1] }); } } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/migrations/cluster-store/2.4.1.ts b/src/migrations/cluster-store/2.4.1.ts index 5789f6cc36..f9de1ed6d8 100644 --- a/src/migrations/cluster-store/2.4.1.ts +++ b/src/migrations/cluster-store/2.4.1.ts @@ -11,4 +11,4 @@ export default migration({ store.set(contextName, { kubeConfig: cluster.kubeConfig, icon: cluster.icon || null, preferences: cluster.preferences || {} }); } } -}) +}); diff --git a/src/migrations/cluster-store/2.6.0-beta.2.ts b/src/migrations/cluster-store/2.6.0-beta.2.ts index 0e13afe7a9..3114202ed1 100644 --- a/src/migrations/cluster-store/2.6.0-beta.2.ts +++ b/src/migrations/cluster-store/2.6.0-beta.2.ts @@ -6,7 +6,7 @@ export default migration({ run(store, log) { for (const value of store) { const clusterKey = value[0]; - if (clusterKey === "__internal__") continue + if (clusterKey === "__internal__") continue; const cluster = value[1]; if (!cluster.preferences) cluster.preferences = {}; if (cluster.icon) { @@ -16,4 +16,4 @@ export default migration({ store.set(clusterKey, { contextName: clusterKey, kubeConfig: value[1].kubeConfig, preferences: value[1].preferences }); } } -}) +}); diff --git a/src/migrations/cluster-store/2.6.0-beta.3.ts b/src/migrations/cluster-store/2.6.0-beta.3.ts index 11f1a3bce9..7f17440e60 100644 --- a/src/migrations/cluster-store/2.6.0-beta.3.ts +++ b/src/migrations/cluster-store/2.6.0-beta.3.ts @@ -1,38 +1,38 @@ import { migration } from "../migration-wrapper"; -import yaml from "js-yaml" +import yaml from "js-yaml"; export default migration({ version: "2.6.0-beta.3", run(store, log) { for (const value of store) { const clusterKey = value[0]; - if (clusterKey === "__internal__") continue + if (clusterKey === "__internal__") continue; const cluster = value[1]; - if (!cluster.kubeConfig) continue - const kubeConfig = yaml.safeLoad(cluster.kubeConfig) - if (!kubeConfig.hasOwnProperty('users')) continue - const userObj = kubeConfig.users[0] + if (!cluster.kubeConfig) continue; + const kubeConfig = yaml.safeLoad(cluster.kubeConfig); + if (!kubeConfig.hasOwnProperty('users')) continue; + const userObj = kubeConfig.users[0]; if (userObj) { - const user = userObj.user + const user = userObj.user; if (user["auth-provider"] && user["auth-provider"].config) { - const authConfig = user["auth-provider"].config + const authConfig = user["auth-provider"].config; if (authConfig["access-token"]) { - authConfig["access-token"] = `${authConfig["access-token"]}` + authConfig["access-token"] = `${authConfig["access-token"]}`; } if (authConfig.expiry) { - authConfig.expiry = `${authConfig.expiry}` + authConfig.expiry = `${authConfig.expiry}`; } - log(authConfig) - user["auth-provider"].config = authConfig + log(authConfig); + user["auth-provider"].config = authConfig; kubeConfig.users = [{ name: userObj.name, user: user - }] - cluster.kubeConfig = yaml.safeDump(kubeConfig) - store.set(clusterKey, cluster) + }]; + cluster.kubeConfig = yaml.safeDump(kubeConfig); + store.set(clusterKey, cluster); } } } } -}) +}); diff --git a/src/migrations/cluster-store/2.7.0-beta.0.ts b/src/migrations/cluster-store/2.7.0-beta.0.ts index 3e0ae9337f..f1af3de3c9 100644 --- a/src/migrations/cluster-store/2.7.0-beta.0.ts +++ b/src/migrations/cluster-store/2.7.0-beta.0.ts @@ -6,10 +6,10 @@ export default migration({ run(store, log) { for (const value of store) { const clusterKey = value[0]; - if (clusterKey === "__internal__") continue + if (clusterKey === "__internal__") continue; const cluster = value[1]; - cluster.workspace = "default" - store.set(clusterKey, cluster) + cluster.workspace = "default"; + store.set(clusterKey, cluster); } } -}) +}); diff --git a/src/migrations/cluster-store/2.7.0-beta.1.ts b/src/migrations/cluster-store/2.7.0-beta.1.ts index de9e4506d1..52e60ba527 100644 --- a/src/migrations/cluster-store/2.7.0-beta.1.ts +++ b/src/migrations/cluster-store/2.7.0-beta.1.ts @@ -1,25 +1,25 @@ // Add id for clusters and store them to array import { migration } from "../migration-wrapper"; -import { v4 as uuid } from "uuid" +import { v4 as uuid } from "uuid"; export default migration({ version: "2.7.0-beta.1", run(store, log) { - const clusters: any[] = [] + const clusters: any[] = []; for (const value of store) { const clusterKey = value[0]; - if (clusterKey === "__internal__") continue - if (clusterKey === "clusters") continue + if (clusterKey === "__internal__") continue; + if (clusterKey === "clusters") continue; const cluster = value[1]; - cluster.id = uuid() + cluster.id = uuid(); if (!cluster.preferences.clusterName) { - cluster.preferences.clusterName = clusterKey + cluster.preferences.clusterName = clusterKey; } - clusters.push(cluster) - store.delete(clusterKey) + clusters.push(cluster); + store.delete(clusterKey); } if (clusters.length > 0) { - store.set("clusters", clusters) + store.set("clusters", clusters); } } -}) +}); diff --git a/src/migrations/cluster-store/3.6.0-beta.1.ts b/src/migrations/cluster-store/3.6.0-beta.1.ts index 412c77ab96..c7e5889cd9 100644 --- a/src/migrations/cluster-store/3.6.0-beta.1.ts +++ b/src/migrations/cluster-store/3.6.0-beta.1.ts @@ -1,24 +1,24 @@ // Move embedded kubeconfig into separate file and add reference to it to cluster settings // convert file path cluster icons to their base64 encoded versions -import path from "path" -import { app, remote } from "electron" +import path from "path"; +import { app, remote } from "electron"; import { migration } from "../migration-wrapper"; -import fse from "fs-extra" +import fse from "fs-extra"; import { ClusterModel, ClusterStore } from "../../common/cluster-store"; import { loadConfig } from "../../common/kube-helpers"; export default migration({ version: "3.6.0-beta.1", run(store, printLog) { - const userDataPath = (app || remote.app).getPath("userData") + const userDataPath = (app || remote.app).getPath("userData"); const kubeConfigBase = ClusterStore.getCustomKubeConfigPath(""); const storedClusters: ClusterModel[] = store.get("clusters") || []; if (!storedClusters.length) return; fse.ensureDirSync(kubeConfigBase); - printLog("Number of clusters to migrate: ", storedClusters.length) + printLog("Number of clusters to migrate: ", storedClusters.length); const migratedClusters = storedClusters .map(cluster => { /** @@ -31,7 +31,7 @@ export default migration({ delete cluster.kubeConfig; } catch (error) { - printLog(`Failed to migrate Kubeconfig for cluster "${cluster.id}", removing cluster...`, error) + printLog(`Failed to migrate Kubeconfig for cluster "${cluster.id}", removing cluster...`, error); return undefined; } @@ -40,8 +40,8 @@ export default migration({ */ try { if (cluster.preferences?.icon) { - printLog(`migrating ${cluster.preferences.icon} for ${cluster.preferences.clusterName}`) - const iconPath = cluster.preferences.icon.replace("store://", "") + printLog(`migrating ${cluster.preferences.icon} for ${cluster.preferences.clusterName}`); + const iconPath = cluster.preferences.icon.replace("store://", ""); const fileData = fse.readFileSync(path.join(userDataPath, iconPath)); cluster.preferences.icon = `data:;base64,${fileData.toString('base64')}`; @@ -49,7 +49,7 @@ export default migration({ delete cluster.preferences?.icon; } } catch (error) { - printLog(`Failed to migrate cluster icon for cluster "${cluster.id}"`, error) + printLog(`Failed to migrate cluster icon for cluster "${cluster.id}"`, error); delete cluster.preferences.icon; } @@ -59,7 +59,7 @@ export default migration({ // "overwrite" the cluster configs if (migratedClusters.length > 0) { - store.set("clusters", migratedClusters) + store.set("clusters", migratedClusters); } } -}) +}); diff --git a/src/migrations/cluster-store/index.ts b/src/migrations/cluster-store/index.ts index f35e8f6c9c..c546fdaeda 100644 --- a/src/migrations/cluster-store/index.ts +++ b/src/migrations/cluster-store/index.ts @@ -1,13 +1,13 @@ // Cluster store migrations -import version200Beta2 from "./2.0.0-beta.2" -import version241 from "./2.4.1" -import version260Beta2 from "./2.6.0-beta.2" -import version260Beta3 from "./2.6.0-beta.3" -import version270Beta0 from "./2.7.0-beta.0" -import version270Beta1 from "./2.7.0-beta.1" -import version360Beta1 from "./3.6.0-beta.1" -import snap from "./snap" +import version200Beta2 from "./2.0.0-beta.2"; +import version241 from "./2.4.1"; +import version260Beta2 from "./2.6.0-beta.2"; +import version260Beta3 from "./2.6.0-beta.3"; +import version270Beta0 from "./2.7.0-beta.0"; +import version270Beta1 from "./2.7.0-beta.1"; +import version360Beta1 from "./3.6.0-beta.1"; +import snap from "./snap"; export default { ...version200Beta2, @@ -18,4 +18,4 @@ export default { ...version270Beta1, ...version360Beta1, ...snap -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/migrations/cluster-store/snap.ts b/src/migrations/cluster-store/snap.ts index a377ba4268..1136607cd7 100644 --- a/src/migrations/cluster-store/snap.ts +++ b/src/migrations/cluster-store/snap.ts @@ -3,31 +3,31 @@ import { migration } from "../migration-wrapper"; import { ClusterModel, ClusterStore } from "../../common/cluster-store"; import { getAppVersion } from "../../common/utils/app-version"; -import fs from "fs" +import fs from "fs"; export default migration({ version: getAppVersion(), // Run always after upgrade run(store, printLog) { if (!process.env["SNAP"]) return; - printLog("Migrating embedded kubeconfig paths") + printLog("Migrating embedded kubeconfig paths"); const storedClusters: ClusterModel[] = store.get("clusters") || []; if (!storedClusters.length) return; - printLog("Number of clusters to migrate: ", storedClusters.length) + printLog("Number of clusters to migrate: ", storedClusters.length); const migratedClusters = storedClusters .map(cluster => { /** * replace snap version with 'current' in kubeconfig path */ if (!fs.existsSync(cluster.kubeConfigPath)) { - const kubeconfigPath = cluster.kubeConfigPath.replace(/\/snap\/kontena-lens\/[0-9]*\//, "/snap/kontena-lens/current/") - cluster.kubeConfigPath = kubeconfigPath + const kubeconfigPath = cluster.kubeConfigPath.replace(/\/snap\/kontena-lens\/[0-9]*\//, "/snap/kontena-lens/current/"); + cluster.kubeConfigPath = kubeconfigPath; } return cluster; - }) + }); - store.set("clusters", migratedClusters) + store.set("clusters", migratedClusters); } -}) +}); diff --git a/src/migrations/user-store/2.1.0-beta.4.ts b/src/migrations/user-store/2.1.0-beta.4.ts index 24c4cde5e3..e8f6500b05 100644 --- a/src/migrations/user-store/2.1.0-beta.4.ts +++ b/src/migrations/user-store/2.1.0-beta.4.ts @@ -6,4 +6,4 @@ export default migration({ run(store) { store.set("lastSeenAppVersion", "0.0.0"); } -}) +}); diff --git a/src/migrations/user-store/index.ts b/src/migrations/user-store/index.ts index 895bc5ee18..e1e7b8ffc9 100644 --- a/src/migrations/user-store/index.ts +++ b/src/migrations/user-store/index.ts @@ -1,7 +1,7 @@ // User store migrations -import version210Beta4 from "./2.1.0-beta.4" +import version210Beta4 from "./2.1.0-beta.4"; export default { ...version210Beta4, -} +}; diff --git a/src/renderer/api/api-manager.ts b/src/renderer/api/api-manager.ts index a0d90f4a13..98dbe206c7 100644 --- a/src/renderer/api/api-manager.ts +++ b/src/renderer/api/api-manager.ts @@ -24,7 +24,7 @@ export class ApiManager { } protected resolveApi(api: string | KubeApi): KubeApi { - if (typeof api === "string") return this.getApi(api) + if (typeof api === "string") return this.getApi(api); return api; } @@ -41,7 +41,7 @@ export class ApiManager { registerStore(store: KubeObjectStore, apis: KubeApi[] = [store.api]) { apis.forEach(api => { this.stores.set(api, store); - }) + }); } getStore(api: string | KubeApi): KubeObjectStore { diff --git a/src/renderer/api/endpoints/cluster-role-binding.api.ts b/src/renderer/api/endpoints/cluster-role-binding.api.ts index 35e4ded7e7..d566717bff 100644 --- a/src/renderer/api/endpoints/cluster-role-binding.api.ts +++ b/src/renderer/api/endpoints/cluster-role-binding.api.ts @@ -2,9 +2,9 @@ import { RoleBinding } from "./role-binding.api"; import { KubeApi } from "../kube-api"; export class ClusterRoleBinding extends RoleBinding { - static kind = "ClusterRoleBinding" - static namespaced = false - static apiBase = "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings" + static kind = "ClusterRoleBinding"; + static namespaced = false; + static apiBase = "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings"; } export const clusterRoleBindingApi = new KubeApi({ diff --git a/src/renderer/api/endpoints/cluster-role.api.ts b/src/renderer/api/endpoints/cluster-role.api.ts index 8a99f7ad27..9e3c90ca2e 100644 --- a/src/renderer/api/endpoints/cluster-role.api.ts +++ b/src/renderer/api/endpoints/cluster-role.api.ts @@ -4,9 +4,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class ClusterRole extends Role { - static kind = "ClusterRole" - static namespaced = false - static apiBase = "/apis/rbac.authorization.k8s.io/v1/clusterroles" + static kind = "ClusterRole"; + static namespaced = false; + static apiBase = "/apis/rbac.authorization.k8s.io/v1/clusterroles"; } export const clusterRoleApi = new KubeApi({ diff --git a/src/renderer/api/endpoints/cluster.api.ts b/src/renderer/api/endpoints/cluster.api.ts index 4386f28184..43783e1c00 100644 --- a/src/renderer/api/endpoints/cluster.api.ts +++ b/src/renderer/api/endpoints/cluster.api.ts @@ -3,12 +3,12 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; export class ClusterApi extends KubeApi { - static kind = "Cluster" - static namespaced = true + static kind = "Cluster"; + static namespaced = true; async getMetrics(nodeNames: string[], params?: IMetricsReqParams): Promise { const nodes = nodeNames.join("|"); - const opts = { category: "cluster", nodes: nodes } + const opts = { category: "cluster", nodes: nodes }; return metricsApi.getMetrics({ memoryUsage: opts, @@ -52,7 +52,7 @@ export interface IClusterMetrics { export class Cluster extends KubeObject { static kind = "Cluster"; - static apiBase = "/apis/cluster.k8s.io/v1alpha1/clusters" + static apiBase = "/apis/cluster.k8s.io/v1alpha1/clusters"; spec: { clusterNetwork?: { @@ -69,7 +69,7 @@ export class Cluster extends KubeObject { profile: string; }; }; - } + }; status?: { apiEndpoints: { host: string; @@ -84,7 +84,7 @@ export class Cluster extends KubeObject { }; errorMessage?: string; errorReason?: string; - } + }; getStatus() { if (this.metadata.deletionTimestamp) return ClusterStatus.REMOVING; diff --git a/src/renderer/api/endpoints/component-status.api.ts b/src/renderer/api/endpoints/component-status.api.ts index 7f7e04fe2a..fec4dda1da 100644 --- a/src/renderer/api/endpoints/component-status.api.ts +++ b/src/renderer/api/endpoints/component-status.api.ts @@ -8,11 +8,11 @@ export interface IComponentStatusCondition { } export class ComponentStatus extends KubeObject { - static kind = "ComponentStatus" - static namespaced = false - static apiBase = "/api/v1/componentstatuses" + static kind = "ComponentStatus"; + static namespaced = false; + static apiBase = "/api/v1/componentstatuses"; - conditions: IComponentStatusCondition[] + conditions: IComponentStatusCondition[]; getTruthyConditions() { return this.conditions.filter(c => c.status === "True"); diff --git a/src/renderer/api/endpoints/configmap.api.ts b/src/renderer/api/endpoints/configmap.api.ts index 59f3e3b090..042fb59d86 100644 --- a/src/renderer/api/endpoints/configmap.api.ts +++ b/src/renderer/api/endpoints/configmap.api.ts @@ -7,7 +7,7 @@ import { KubeApi } from "../kube-api"; export class ConfigMap extends KubeObject { static kind = "ConfigMap"; static namespaced = true; - static apiBase = "/api/v1/configmaps" + static apiBase = "/api/v1/configmaps"; constructor(data: KubeJsonApiData) { super(data); @@ -16,7 +16,7 @@ export class ConfigMap extends KubeObject { data: { [param: string]: string; - } + }; getKeys(): string[] { return Object.keys(this.data); diff --git a/src/renderer/api/endpoints/crd.api.ts b/src/renderer/api/endpoints/crd.api.ts index 1916d71f1b..02690a2afd 100644 --- a/src/renderer/api/endpoints/crd.api.ts +++ b/src/renderer/api/endpoints/crd.api.ts @@ -7,20 +7,20 @@ type AdditionalPrinterColumnsCommon = { type: "integer" | "number" | "string" | "boolean" | "date"; priority: number; description: string; -} +}; export type AdditionalPrinterColumnsV1 = AdditionalPrinterColumnsCommon & { jsonPath: string; -} +}; type AdditionalPrinterColumnsV1Beta = AdditionalPrinterColumnsCommon & { JSONPath: string; -} +}; export class CustomResourceDefinition extends KubeObject { static kind = "CustomResourceDefinition"; static namespaced = false; - static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions" + static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions"; spec: { group: string; @@ -45,7 +45,7 @@ export class CustomResourceDefinition extends KubeObject { webhook?: any; }; additionalPrinterColumns?: AdditionalPrinterColumnsV1Beta[]; // removed in v1 - } + }; status: { conditions: { lastTransitionTime: string; @@ -62,7 +62,7 @@ export class CustomResourceDefinition extends KubeObject { listKind: string; }; storedVersions: string[]; - } + }; getResourceUrl() { return crdResourcesURL({ @@ -70,25 +70,25 @@ export class CustomResourceDefinition extends KubeObject { group: this.getGroup(), name: this.getPluralName(), } - }) + }); } getResourceApiBase() { const { group } = this.spec; - return `/apis/${group}/${this.getVersion()}/${this.getPluralName()}` + return `/apis/${group}/${this.getVersion()}/${this.getPluralName()}`; } getPluralName() { - return this.getNames().plural + return this.getNames().plural; } getResourceKind() { - return this.spec.names.kind + return this.spec.names.kind; } getResourceTitle() { const name = this.getPluralName(); - return name[0].toUpperCase() + name.substr(1) + return name[0].toUpperCase() + name.substr(1); } getGroup() { @@ -141,7 +141,7 @@ export class CustomResourceDefinition extends KubeObject { ...condition, isReady: status === "True", tooltip: `${message || reason} (${lastTransitionTime})` - } + }; }); } } diff --git a/src/renderer/api/endpoints/cron-job.api.ts b/src/renderer/api/endpoints/cron-job.api.ts index b385647bb9..2cca8bfb3d 100644 --- a/src/renderer/api/endpoints/cron-job.api.ts +++ b/src/renderer/api/endpoints/cron-job.api.ts @@ -7,12 +7,12 @@ import { KubeApi } from "../kube-api"; @autobind() export class CronJob extends KubeObject { - static kind = "CronJob" - static namespaced = true - static apiBase = "/apis/batch/v1beta1/cronjobs" + static kind = "CronJob"; + static namespaced = true; + static apiBase = "/apis/batch/v1beta1/cronjobs"; - kind: string - apiVersion: string + kind: string; + apiVersion: string; metadata: { name: string; namespace: string; @@ -26,7 +26,7 @@ export class CronJob extends KubeObject { annotations: { [key: string]: string; }; - } + }; spec: { schedule: string; concurrencyPolicy: string; @@ -59,23 +59,23 @@ export class CronJob extends KubeObject { }; successfulJobsHistoryLimit: number; failedJobsHistoryLimit: number; - } + }; status: { lastScheduleTime?: string; - } + }; getSuspendFlag() { - return this.spec.suspend.toString() + return this.spec.suspend.toString(); } getLastScheduleTime() { - if (!this.status.lastScheduleTime) return "-" - const diff = moment().diff(this.status.lastScheduleTime) - return formatDuration(diff, true) + if (!this.status.lastScheduleTime) return "-"; + const diff = moment().diff(this.status.lastScheduleTime); + return formatDuration(diff, true); } getSchedule() { - return this.spec.schedule + return this.spec.schedule; } isNeverRun() { diff --git a/src/renderer/api/endpoints/daemon-set.api.ts b/src/renderer/api/endpoints/daemon-set.api.ts index d947293c1c..63fc6363e4 100644 --- a/src/renderer/api/endpoints/daemon-set.api.ts +++ b/src/renderer/api/endpoints/daemon-set.api.ts @@ -6,9 +6,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class DaemonSet extends WorkloadKubeObject { - static kind = "DaemonSet" - static namespaced = true - static apiBase = "/apis/apps/v1/daemonsets" + static kind = "DaemonSet"; + static namespaced = true; + static apiBase = "/apis/apps/v1/daemonsets"; spec: { selector: { @@ -51,7 +51,7 @@ export class DaemonSet extends WorkloadKubeObject { }; }; revisionHistoryLimit: number; - } + }; status: { currentNumberScheduled: number; numberMisscheduled: number; @@ -61,12 +61,12 @@ export class DaemonSet extends WorkloadKubeObject { updatedNumberScheduled: number; numberAvailable: number; numberUnavailable: number; - } + }; getImages() { - const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []) - const initContainers: IPodContainer[] = get(this, "spec.template.spec.initContainers", []) - return [...containers, ...initContainers].map(container => container.image) + const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []); + const initContainers: IPodContainer[] = get(this, "spec.template.spec.initContainers", []); + return [...containers, ...initContainers].map(container => container.image); } } diff --git a/src/renderer/api/endpoints/deployment.api.ts b/src/renderer/api/endpoints/deployment.api.ts index b21495ecc1..28ed71f86a 100644 --- a/src/renderer/api/endpoints/deployment.api.ts +++ b/src/renderer/api/endpoints/deployment.api.ts @@ -6,13 +6,13 @@ import { KubeApi } from "../kube-api"; export class DeploymentApi extends KubeApi { protected getScaleApiUrl(params: { namespace: string; name: string }) { - return this.getUrl(params) + "/scale" + return this.getUrl(params) + "/scale"; } getReplicas(params: { namespace: string; name: string }): Promise { return this.request .get(this.getScaleApiUrl(params)) - .then(({ status }: any) => status?.replicas) + .then(({ status }: any) => status?.replicas); } scale(params: { namespace: string; name: string }, replicas: number) { @@ -23,7 +23,7 @@ export class DeploymentApi extends KubeApi { replicas: replicas } } - }) + }); } restart(params: { namespace: string; name: string }) { @@ -42,15 +42,15 @@ export class DeploymentApi extends KubeApi { headers: { 'content-type': 'application/strategic-merge-patch+json' } - }) + }); } } @autobind() export class Deployment extends WorkloadKubeObject { - static kind = "Deployment" - static namespaced = true - static apiBase = "/apis/apps/v1/deployments" + static kind = "Deployment"; + static namespaced = true; + static apiBase = "/apis/apps/v1/deployments"; spec: { replicas: number; @@ -151,7 +151,7 @@ export class Deployment extends WorkloadKubeObject { maxSurge: number; }; }; - } + }; status: { observedGeneration: number; replicas: number; @@ -167,19 +167,19 @@ export class Deployment extends WorkloadKubeObject { reason: string; message: string; }[]; - } + }; getConditions(activeOnly = false) { - const { conditions } = this.status - if (!conditions) return [] + const { conditions } = this.status; + if (!conditions) return []; if (activeOnly) { - return conditions.filter(c => c.status === "True") + return conditions.filter(c => c.status === "True"); } - return conditions + return conditions; } getConditionsText(activeOnly = true) { - return this.getConditions(activeOnly).map(({ type }) => type).join(" ") + return this.getConditions(activeOnly).map(({ type }) => type).join(" "); } getReplicas() { diff --git a/src/renderer/api/endpoints/endpoint.api.ts b/src/renderer/api/endpoints/endpoint.api.ts index 4f4afc9b17..121836a637 100644 --- a/src/renderer/api/endpoints/endpoint.api.ts +++ b/src/renderer/api/endpoints/endpoint.api.ts @@ -42,22 +42,22 @@ export class EndpointAddress implements IEndpointAddress { }; constructor(data: IEndpointAddress) { - Object.assign(this, data) + Object.assign(this, data); } getId() { - return this.ip + return this.ip; } getName() { - return this.hostname + return this.hostname; } getTargetRef(): ITargetRef { if (this.targetRef) { - return Object.assign(this.targetRef, {apiVersion: "v1"}) + return Object.assign(this.targetRef, {apiVersion: "v1"}); } else { - return null + return null; } } } @@ -68,7 +68,7 @@ export class EndpointSubset implements IEndpointSubset { ports: IEndpointPort[]; constructor(data: IEndpointSubset) { - Object.assign(this, data) + Object.assign(this, data); } getAddresses(): EndpointAddress[] { @@ -83,26 +83,26 @@ export class EndpointSubset implements IEndpointSubset { toString(): string { if(!this.addresses) { - return "" + return ""; } return this.addresses.map(address => { if (!this.ports) { - return address.ip + return address.ip; } return this.ports.map(port => { - return `${address.ip}:${port.port}` - }).join(", ") - }).join(", ") + return `${address.ip}:${port.port}`; + }).join(", "); + }).join(", "); } } @autobind() export class Endpoint extends KubeObject { - static kind = "Endpoints" - static namespaced = true - static apiBase = "/api/v1/endpoints" + static kind = "Endpoints"; + static namespaced = true; + static apiBase = "/api/v1/endpoints"; - subsets: IEndpointSubset[] + subsets: IEndpointSubset[]; getEndpointSubsets(): EndpointSubset[] { const subsets = this.subsets || []; @@ -111,9 +111,9 @@ export class Endpoint extends KubeObject { toString(): string { if(this.subsets) { - return this.getEndpointSubsets().map(es => es.toString()).join(", ") + return this.getEndpointSubsets().map(es => es.toString()).join(", "); } else { - return "" + return ""; } } diff --git a/src/renderer/api/endpoints/events.api.ts b/src/renderer/api/endpoints/events.api.ts index 0608a3d44b..51dbf3c3b5 100644 --- a/src/renderer/api/endpoints/events.api.ts +++ b/src/renderer/api/endpoints/events.api.ts @@ -6,9 +6,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class KubeEvent extends KubeObject { - static kind = "Event" - static namespaced = true - static apiBase = "/api/v1/events" + static kind = "Event"; + static namespaced = true; + static apiBase = "/api/v1/events"; involvedObject: { kind: string; @@ -18,41 +18,41 @@ export class KubeEvent extends KubeObject { apiVersion: string; resourceVersion: string; fieldPath: string; - } - reason: string - message: string + }; + reason: string; + message: string; source: { component: string; host: string; - } - firstTimestamp: string - lastTimestamp: string - count: number - type: string - eventTime: null - reportingComponent: string - reportingInstance: string + }; + firstTimestamp: string; + lastTimestamp: string; + count: number; + type: string; + eventTime: null; + reportingComponent: string; + reportingInstance: string; isWarning() { return this.type === "Warning"; } getSource() { - const { component, host } = this.source - return `${component} ${host || ""}` + const { component, host } = this.source; + return `${component} ${host || ""}`; } getFirstSeenTime() { - const diff = moment().diff(this.firstTimestamp) - return formatDuration(diff, true) + const diff = moment().diff(this.firstTimestamp); + return formatDuration(diff, true); } getLastSeenTime() { - const diff = moment().diff(this.lastTimestamp) - return formatDuration(diff, true) + const diff = moment().diff(this.lastTimestamp); + return formatDuration(diff, true); } } export const eventApi = new KubeApi({ objectConstructor: KubeEvent, -}) +}); diff --git a/src/renderer/api/endpoints/helm-charts.api.ts b/src/renderer/api/endpoints/helm-charts.api.ts index 8943cd49df..e6328f136b 100644 --- a/src/renderer/api/endpoints/helm-charts.api.ts +++ b/src/renderer/api/endpoints/helm-charts.api.ts @@ -41,7 +41,7 @@ export const helmChartsApi = { return { readme, versions, - } + }; }); }, @@ -61,27 +61,27 @@ export class HelmChart { return new HelmChart(data); } - apiVersion: string - name: string - version: string - repo: string - kubeVersion?: string - created: string - description?: string - digest: string - keywords?: string[] - home?: string - sources?: string[] + apiVersion: string; + name: string; + version: string; + repo: string; + kubeVersion?: string; + created: string; + description?: string; + digest: string; + keywords?: string[]; + home?: string; + sources?: string[]; maintainers?: { name: string; email: string; url: string; - }[] - engine?: string - icon?: string - appVersion?: string - deprecated?: boolean - tillerVersion?: string + }[]; + engine?: string; + icon?: string; + appVersion?: string; + deprecated?: boolean; + tillerVersion?: string; getId() { return this.digest; diff --git a/src/renderer/api/endpoints/helm-releases.api.ts b/src/renderer/api/endpoints/helm-releases.api.ts index 9051936ac8..0ddbf1c734 100644 --- a/src/renderer/api/endpoints/helm-releases.api.ts +++ b/src/renderer/api/endpoints/helm-releases.api.ts @@ -82,7 +82,7 @@ export const helmReleasesApi = { return { ...details, resources - } + }; }); }, @@ -135,13 +135,13 @@ export class HelmRelease implements ItemObject { return new HelmRelease(data); } - appVersion: string - name: string - namespace: string - chart: string - status: string - updated: string - revision: string + appVersion: string; + name: string; + namespace: string; + chart: string; + status: string; + updated: string; + revision: string; getId() { return this.namespace + this.name; @@ -156,12 +156,12 @@ export class HelmRelease implements ItemObject { } getChart(withVersion = false) { - let chart = this.chart + let chart = this.chart; if(!withVersion && this.getVersion() != "" ) { - const search = new RegExp(`-${this.getVersion()}`) + const search = new RegExp(`-${this.getVersion()}`); chart = chart.replace(search, ""); } - return chart + return chart; } getRevision() { @@ -173,12 +173,12 @@ export class HelmRelease implements ItemObject { } getVersion() { - const versions = this.chart.match(/(v?\d+)[^-].*$/) + const versions = this.chart.match(/(v?\d+)[^-].*$/); if (versions) { - return versions[0] + return versions[0]; } else { - return "" + return ""; } } diff --git a/src/renderer/api/endpoints/hpa.api.ts b/src/renderer/api/endpoints/hpa.api.ts index f55f6d327f..79e6cada0f 100644 --- a/src/renderer/api/endpoints/hpa.api.ts +++ b/src/renderer/api/endpoints/hpa.api.ts @@ -20,7 +20,7 @@ export type IHpaMetricData = T & { currentAverageValue?: string; targetAverageUtilization?: number; targetAverageValue?: string; -} +}; export interface IHpaMetric { [kind: string]: IHpaMetricData; @@ -41,7 +41,7 @@ export interface IHpaMetric { export class HorizontalPodAutoscaler extends KubeObject { static kind = "HorizontalPodAutoscaler"; static namespaced = true; - static apiBase = "/apis/autoscaling/v2beta1/horizontalpodautoscalers" + static apiBase = "/apis/autoscaling/v2beta1/horizontalpodautoscalers"; spec: { scaleTargetRef: { @@ -52,7 +52,7 @@ export class HorizontalPodAutoscaler extends KubeObject { minReplicas: number; maxReplicas: number; metrics: IHpaMetric[]; - } + }; status: { currentReplicas: number; desiredReplicas: number; @@ -64,7 +64,7 @@ export class HorizontalPodAutoscaler extends KubeObject { status: string; type: string; }[]; - } + }; getMaxPods() { return this.spec.maxReplicas || 0; @@ -86,7 +86,7 @@ export class HorizontalPodAutoscaler extends KubeObject { ...condition, isReady: status === "True", tooltip: `${message || reason} (${lastTransitionTime})` - } + }; }); } @@ -102,7 +102,7 @@ export class HorizontalPodAutoscaler extends KubeObject { const { type, resource, pods, object, external } = metric; switch (type) { case HpaMetricType.Resource: - return resource.name + return resource.name; case HpaMetricType.Pods: return pods.metricName; case HpaMetricType.Object: @@ -128,7 +128,7 @@ export class HorizontalPodAutoscaler extends KubeObject { } if (target) { targetValue = target.targetAverageUtilization || target.targetAverageValue || target.targetValue; - if (target.targetAverageUtilization) targetValue += "%" + if (target.targetAverageUtilization) targetValue += "%"; } return `${currentValue} / ${targetValue}`; } diff --git a/src/renderer/api/endpoints/index.ts b/src/renderer/api/endpoints/index.ts index 337d193043..f1202b9122 100644 --- a/src/renderer/api/endpoints/index.ts +++ b/src/renderer/api/endpoints/index.ts @@ -1,35 +1,35 @@ // Kubernetes apis // Docs: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/ -export * from "./cluster.api" -export * from "./cluster-role.api" -export * from "./cluster-role-binding.api" -export * from "./configmap.api" -export * from "./crd.api" -export * from "./cron-job.api" -export * from "./daemon-set.api" -export * from "./deployment.api" -export * from "./endpoint.api" -export * from "./events.api" -export * from "./hpa.api" -export * from "./ingress.api" -export * from "./job.api" -export * from "./namespaces.api" -export * from "./network-policy.api" -export * from "./nodes.api" -export * from "./persistent-volume.api" -export * from "./persistent-volume-claims.api" -export * from "./pods.api" -export * from "./poddisruptionbudget.api" -export * from "./pod-metrics.api" -export * from "./podsecuritypolicy.api" -export * from "./replica-set.api" -export * from "./resource-quota.api" -export * from "./role.api" -export * from "./role-binding.api" -export * from "./secret.api" -export * from "./selfsubjectrulesreviews.api" -export * from "./service.api" -export * from "./service-accounts.api" -export * from "./stateful-set.api" -export * from "./storage-class.api" +export * from "./cluster.api"; +export * from "./cluster-role.api"; +export * from "./cluster-role-binding.api"; +export * from "./configmap.api"; +export * from "./crd.api"; +export * from "./cron-job.api"; +export * from "./daemon-set.api"; +export * from "./deployment.api"; +export * from "./endpoint.api"; +export * from "./events.api"; +export * from "./hpa.api"; +export * from "./ingress.api"; +export * from "./job.api"; +export * from "./namespaces.api"; +export * from "./network-policy.api"; +export * from "./nodes.api"; +export * from "./persistent-volume.api"; +export * from "./persistent-volume-claims.api"; +export * from "./pods.api"; +export * from "./poddisruptionbudget.api"; +export * from "./pod-metrics.api"; +export * from "./podsecuritypolicy.api"; +export * from "./replica-set.api"; +export * from "./resource-quota.api"; +export * from "./role.api"; +export * from "./role-binding.api"; +export * from "./secret.api"; +export * from "./selfsubjectrulesreviews.api"; +export * from "./service.api"; +export * from "./service-accounts.api"; +export * from "./stateful-set.api"; +export * from "./storage-class.api"; diff --git a/src/renderer/api/endpoints/ingress.api.ts b/src/renderer/api/endpoints/ingress.api.ts index 1f3e1659f0..0594e3446e 100644 --- a/src/renderer/api/endpoints/ingress.api.ts +++ b/src/renderer/api/endpoints/ingress.api.ts @@ -5,7 +5,7 @@ import { KubeApi } from "../kube-api"; export class IngressApi extends KubeApi { getMetrics(ingress: string, namespace: string): Promise { - const opts = { category: "ingress", ingress } + const opts = { category: "ingress", ingress }; return metricsApi.getMetrics({ bytesSentSuccess: opts, bytesSentFailure: opts, @@ -31,9 +31,9 @@ export interface ILoadBalancerIngress { } @autobind() export class Ingress extends KubeObject { - static kind = "Ingress" - static namespaced = true - static apiBase = "/apis/extensions/v1beta1/ingresses" + static kind = "Ingress"; + static namespaced = true; + static apiBase = "/apis/extensions/v1beta1/ingresses"; spec: { tls: { @@ -55,59 +55,59 @@ export class Ingress extends KubeObject { serviceName: string; servicePort: number; }; - } + }; status: { loadBalancer: { ingress: ILoadBalancerIngress[]; }; - } + }; getRoutes() { - const { spec: { tls, rules } } = this - if (!rules) return [] + const { spec: { tls, rules } } = this; + if (!rules) return []; - let protocol = "http" - const routes: string[] = [] + let protocol = "http"; + const routes: string[] = []; if (tls && tls.length > 0) { - protocol += "s" + protocol += "s"; } rules.map(rule => { - const host = rule.host ? rule.host : "*" + const host = rule.host ? rule.host : "*"; if (rule.http && rule.http.paths) { rule.http.paths.forEach(path => { - routes.push(protocol + "://" + host + (path.path || "/") + " ⇢ " + path.backend.serviceName + ":" + path.backend.servicePort) - }) + routes.push(protocol + "://" + host + (path.path || "/") + " ⇢ " + path.backend.serviceName + ":" + path.backend.servicePort); + }); } - }) + }); return routes; } getHosts() { - const { spec: { rules } } = this - if (!rules) return [] - return rules.filter(rule => rule.host).map(rule => rule.host) + const { spec: { rules } } = this; + if (!rules) return []; + return rules.filter(rule => rule.host).map(rule => rule.host); } getPorts() { - const ports: number[] = [] - const { spec: { tls, rules, backend } } = this - const httpPort = 80 - const tlsPort = 443 + const ports: number[] = []; + const { spec: { tls, rules, backend } } = this; + const httpPort = 80; + const tlsPort = 443; if (rules && rules.length > 0) { if (rules.some(rule => rule.hasOwnProperty("http"))) { - ports.push(httpPort) + ports.push(httpPort); } } else { if (backend && backend.servicePort) { - ports.push(backend.servicePort) + ports.push(backend.servicePort); } } if (tls && tls.length > 0) { - ports.push(tlsPort) + ports.push(tlsPort); } - return ports.join(", ") + return ports.join(", "); } getLoadBalancers() { @@ -115,7 +115,7 @@ export class Ingress extends KubeObject { return (loadBalancer.ingress ?? []).map(address => ( address.hostname || address.ip - )) + )); } } diff --git a/src/renderer/api/endpoints/job.api.ts b/src/renderer/api/endpoints/job.api.ts index 59e9e9ba8f..1dc78fdc94 100644 --- a/src/renderer/api/endpoints/job.api.ts +++ b/src/renderer/api/endpoints/job.api.ts @@ -7,9 +7,9 @@ import { JsonApiParams } from "../json-api"; @autobind() export class Job extends WorkloadKubeObject { - static kind = "Job" - static namespaced = true - static apiBase = "/apis/batch/v1/jobs" + static kind = "Job"; + static namespaced = true; + static apiBase = "/apis/batch/v1/jobs"; spec: { parallelism?: number; @@ -56,7 +56,7 @@ export class Job extends WorkloadKubeObject { serviceAccountName?: string; serviceAccount?: string; schedulerName?: string; - } + }; status: { conditions: { type: string; @@ -68,7 +68,7 @@ export class Job extends WorkloadKubeObject { startTime: string; completionTime: string; succeeded: number; - } + }; getDesiredCompletions() { return this.spec.completions || 0; @@ -91,15 +91,15 @@ export class Job extends WorkloadKubeObject { } getImages() { - const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []) - return [...containers].map(container => container.image) + const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []); + return [...containers].map(container => container.image); } delete() { const params: JsonApiParams = { query: { propagationPolicy: "Background" } - } - return super.delete(params) + }; + return super.delete(params); } } diff --git a/src/renderer/api/endpoints/metrics.api.ts b/src/renderer/api/endpoints/metrics.api.ts index 81d2f1d500..7f30487d44 100644 --- a/src/renderer/api/endpoints/metrics.api.ts +++ b/src/renderer/api/endpoints/metrics.api.ts @@ -66,7 +66,7 @@ export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics { } as IMetricsResult], }, status: "", - } + }; } const { result } = metrics.data; @@ -78,7 +78,7 @@ export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics { if (!res.values || !res.values.length) return; while (res.values.length < frames) { const timestamp = moment.unix(res.values[0][0]).subtract(1, "minute").unix(); - res.values.unshift([timestamp, "0"]) + res.values.unshift([timestamp, "0"]); } }); } @@ -103,7 +103,7 @@ export function getItemMetrics(metrics: { [key: string]: IMetrics }, itemName: s const itemMetrics = { ...metrics }; for (const metric in metrics) { if (!metrics[metric]?.data?.result) { - continue + continue; } const results = metrics[metric].data.result; const result = results.find(res => Object.values(res.metric)[0] == itemName); diff --git a/src/renderer/api/endpoints/namespaces.api.ts b/src/renderer/api/endpoints/namespaces.api.ts index c615789cd9..430565bf57 100644 --- a/src/renderer/api/endpoints/namespaces.api.ts +++ b/src/renderer/api/endpoints/namespaces.api.ts @@ -15,7 +15,7 @@ export class Namespace extends KubeObject { status?: { phase: string; - } + }; getStatus() { return this.status ? this.status.phase : "-"; diff --git a/src/renderer/api/endpoints/network-policy.api.ts b/src/renderer/api/endpoints/network-policy.api.ts index bfae6cbcdc..4ecd333854 100644 --- a/src/renderer/api/endpoints/network-policy.api.ts +++ b/src/renderer/api/endpoints/network-policy.api.ts @@ -37,9 +37,9 @@ export interface IPolicyEgress { @autobind() export class NetworkPolicy extends KubeObject { - static kind = "NetworkPolicy" - static namespaced = true - static apiBase = "/apis/networking.k8s.io/v1/networkpolicies" + static kind = "NetworkPolicy"; + static namespaced = true; + static apiBase = "/apis/networking.k8s.io/v1/networkpolicies"; spec: { podSelector: { @@ -51,13 +51,13 @@ export class NetworkPolicy extends KubeObject { policyTypes: string[]; ingress: IPolicyIngress[]; egress: IPolicyEgress[]; - } + }; getMatchLabels(): string[] { if (!this.spec.podSelector || !this.spec.podSelector.matchLabels) return []; return Object .entries(this.spec.podSelector.matchLabels) - .map(data => data.join(":")) + .map(data => data.join(":")); } getTypes(): string[] { diff --git a/src/renderer/api/endpoints/nodes.api.ts b/src/renderer/api/endpoints/nodes.api.ts index f8031a9824..c85cd8f9b0 100644 --- a/src/renderer/api/endpoints/nodes.api.ts +++ b/src/renderer/api/endpoints/nodes.api.ts @@ -5,7 +5,7 @@ import { KubeApi } from "../kube-api"; export class NodesApi extends KubeApi { getMetrics(): Promise { - const opts = { category: "nodes"} + const opts = { category: "nodes"}; return metricsApi.getMetrics({ memoryUsage: opts, @@ -30,9 +30,9 @@ export interface INodeMetrics { @autobind() export class Node extends KubeObject { - static kind = "Node" - static namespaced = false - static apiBase = "/api/v1/nodes" + static kind = "Node"; + static namespaced = false; + static apiBase = "/api/v1/nodes"; spec: { podCIDR: string; @@ -43,7 +43,7 @@ export class Node extends KubeObject { effect: string; }[]; unschedulable?: boolean; - } + }; status: { capacity: { cpu: string; @@ -83,15 +83,15 @@ export class Node extends KubeObject { names: string[]; sizeBytes: number; }[]; - } + }; getNodeConditionText() { - const { conditions } = this.status - if (!conditions) return "" + const { conditions } = this.status; + if (!conditions) return ""; return conditions.reduce((types, current) => { - if (current.status !== "True") return "" - return types += ` ${current.type}` - }, "") + if (current.status !== "True") return ""; + return types += ` ${current.type}`; + }, ""); } getTaints() { @@ -101,23 +101,23 @@ export class Node extends KubeObject { getRoleLabels() { const roleLabels = Object.keys(this.metadata.labels).filter(key => key.includes("node-role.kubernetes.io") - ).map(key => key.match(/([^/]+$)/)[0]) // all after last slash + ).map(key => key.match(/([^/]+$)/)[0]); // all after last slash if (this.metadata.labels["kubernetes.io/role"] != undefined) { - roleLabels.push(this.metadata.labels["kubernetes.io/role"]) + roleLabels.push(this.metadata.labels["kubernetes.io/role"]); } - return roleLabels.join(", ") + return roleLabels.join(", "); } getCpuCapacity() { - if (!this.status.capacity || !this.status.capacity.cpu) return 0 - return cpuUnitsToNumber(this.status.capacity.cpu) + if (!this.status.capacity || !this.status.capacity.cpu) return 0; + return cpuUnitsToNumber(this.status.capacity.cpu); } getMemoryCapacity() { - if (!this.status.capacity || !this.status.capacity.memory) return 0 - return unitsToBytes(this.status.capacity.memory) + if (!this.status.capacity || !this.status.capacity.memory) return 0; + return unitsToBytes(this.status.capacity.memory); } getConditions() { @@ -144,16 +144,16 @@ export class Node extends KubeObject { } getOperatingSystem(): string { - const label = this.getLabels().find(label => label.startsWith("kubernetes.io/os=")) + const label = this.getLabels().find(label => label.startsWith("kubernetes.io/os=")); if (label) { - return label.split("=", 2)[1] + return label.split("=", 2)[1]; } - return "linux" + return "linux"; } isUnschedulable() { - return this.spec.unschedulable + return this.spec.unschedulable; } } diff --git a/src/renderer/api/endpoints/persistent-volume-claims.api.ts b/src/renderer/api/endpoints/persistent-volume-claims.api.ts index 4e719c529b..9aa73bb0bc 100644 --- a/src/renderer/api/endpoints/persistent-volume-claims.api.ts +++ b/src/renderer/api/endpoints/persistent-volume-claims.api.ts @@ -23,9 +23,9 @@ export interface IPvcMetrics { @autobind() export class PersistentVolumeClaim extends KubeObject { - static kind = "PersistentVolumeClaim" - static namespaced = true - static apiBase = "/api/v1/persistentvolumeclaims" + static kind = "PersistentVolumeClaim"; + static namespaced = true; + static apiBase = "/api/v1/persistentvolumeclaims"; spec: { accessModes: string[]; @@ -45,19 +45,19 @@ export class PersistentVolumeClaim extends KubeObject { storage: string; // 8Gi }; }; - } + }; status: { phase: string; // Pending - } + }; getPods(allPods: Pod[]): Pod[] { - const pods = allPods.filter(pod => pod.getNs() === this.getNs()) + const pods = allPods.filter(pod => pod.getNs() === this.getNs()); return pods.filter(pod => { return pod.getVolumes().filter(volume => volume.persistentVolumeClaim && volume.persistentVolumeClaim.claimName === this.getName() - ).length > 0 - }) + ).length > 0; + }); } getStorage(): string { @@ -78,7 +78,7 @@ export class PersistentVolumeClaim extends KubeObject { getStatus(): string { if (this.status) return this.status.phase; - return "-" + return "-"; } } diff --git a/src/renderer/api/endpoints/persistent-volume.api.ts b/src/renderer/api/endpoints/persistent-volume.api.ts index 8ab2efbf89..5e31eeb028 100644 --- a/src/renderer/api/endpoints/persistent-volume.api.ts +++ b/src/renderer/api/endpoints/persistent-volume.api.ts @@ -5,9 +5,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class PersistentVolume extends KubeObject { - static kind = "PersistentVolume" - static namespaced = false - static apiBase = "/api/v1/persistentvolumes" + static kind = "PersistentVolume"; + static namespaced = false; + static apiBase = "/api/v1/persistentvolumes"; spec: { capacity: { @@ -38,17 +38,17 @@ export class PersistentVolume extends KubeObject { path: string; server: string; }; - } + }; status: { phase: string; reason?: string; - } + }; getCapacity(inBytes = false) { const capacity = this.spec.capacity; if (capacity) { - if (inBytes) return unitsToBytes(capacity.storage) + if (inBytes) return unitsToBytes(capacity.storage); return capacity.storage; } return 0; diff --git a/src/renderer/api/endpoints/pod-metrics.api.ts b/src/renderer/api/endpoints/pod-metrics.api.ts index 7e01a1a990..acf6e7b20f 100644 --- a/src/renderer/api/endpoints/pod-metrics.api.ts +++ b/src/renderer/api/endpoints/pod-metrics.api.ts @@ -2,19 +2,19 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; export class PodMetrics extends KubeObject { - static kind = "Pod" - static namespaced = true - static apiBase = "/apis/metrics.k8s.io/v1beta1/pods" + static kind = "Pod"; + static namespaced = true; + static apiBase = "/apis/metrics.k8s.io/v1beta1/pods"; - timestamp: string - window: string + timestamp: string; + window: string; containers: { name: string; usage: { cpu: string; memory: string; }; - }[] + }[]; } export const podMetricsApi = new KubeApi({ diff --git a/src/renderer/api/endpoints/poddisruptionbudget.api.ts b/src/renderer/api/endpoints/poddisruptionbudget.api.ts index ea7e0575ff..b76260ae6f 100644 --- a/src/renderer/api/endpoints/poddisruptionbudget.api.ts +++ b/src/renderer/api/endpoints/poddisruptionbudget.api.ts @@ -12,13 +12,13 @@ export class PodDisruptionBudget extends KubeObject { minAvailable: string; maxUnavailable: string; selector: { matchLabels: { [app: string]: string } }; - } + }; status: { currentHealthy: number desiredHealthy: number disruptionsAllowed: number expectedPods: number - } + }; getSelectors() { const selector = this.spec.selector; diff --git a/src/renderer/api/endpoints/pods.api.ts b/src/renderer/api/endpoints/pods.api.ts index 92b7059272..a5c833b5fa 100644 --- a/src/renderer/api/endpoints/pods.api.ts +++ b/src/renderer/api/endpoints/pods.api.ts @@ -11,7 +11,7 @@ export class PodsApi extends KubeApi { getMetrics(pods: Pod[], namespace: string, selector = "pod, namespace"): Promise { const podSelector = pods.map(pod => pod.getName()).join("|"); - const opts = { category: "pods", pods: podSelector, namespace, selector } + const opts = { category: "pods", pods: podSelector, namespace, selector }; return metricsApi.getMetrics({ cpuUsage: opts, @@ -171,9 +171,9 @@ export interface IPodContainerStatus { @autobind() export class Pod extends WorkloadKubeObject { - static kind = "Pod" - static namespaced = true - static apiBase = "/api/v1/pods" + static kind = "Pod"; + static namespaced = true; + static apiBase = "/api/v1/pods"; spec: { volumes?: { @@ -215,7 +215,7 @@ export class Pod extends WorkloadKubeObject { tolerationSeconds: number; }[]; affinity: IAffinity; - } + }; status: { phase: string; conditions: { @@ -231,7 +231,7 @@ export class Pod extends WorkloadKubeObject { containerStatuses?: IPodContainerStatus[]; qosClass: string; reason?: string; - } + }; getInitContainers() { return this.spec.initContainers || []; @@ -246,11 +246,11 @@ export class Pod extends WorkloadKubeObject { } getRunningContainers() { - const statuses = this.getContainerStatuses() + const statuses = this.getContainerStatuses(); return this.getAllContainers().filter(container => { - return statuses.find(status => status.name === container.name && !!status.state["running"]) + return statuses.find(status => status.name === container.name && !!status.state["running"]); } - ) + ); } getContainerStatuses(includeInitContainers = true) { @@ -323,7 +323,7 @@ export class Pod extends WorkloadKubeObject { const { reason } = state.terminated; message = reason ? reason : "Terminated"; } - }) + }); } if (message) return message; return this.getStatusPhase(); @@ -348,32 +348,32 @@ export class Pod extends WorkloadKubeObject { } getNodeSelectors(): string[] { - const { nodeSelector } = this.spec - if (!nodeSelector) return [] - return Object.entries(nodeSelector).map(values => values.join(": ")) + const { nodeSelector } = this.spec; + if (!nodeSelector) return []; + return Object.entries(nodeSelector).map(values => values.join(": ")); } getTolerations() { - return this.spec.tolerations || [] + return this.spec.tolerations || []; } getAffinity(): IAffinity { - return this.spec.affinity + return this.spec.affinity; } hasIssues() { const notReady = !!this.getConditions().find(condition => { - return condition.type == "Ready" && condition.status !== "True" + return condition.type == "Ready" && condition.status !== "True"; }); const crashLoop = !!this.getContainerStatuses().find(condition => { - const waiting = condition.state.waiting - return (waiting && waiting.reason == "CrashLoopBackOff") - }) + const waiting = condition.state.waiting; + return (waiting && waiting.reason == "CrashLoopBackOff"); + }); return ( notReady || crashLoop || this.getStatusPhase() !== "Running" - ) + ); } getLivenessProbe(container: IPodContainer) { @@ -418,14 +418,14 @@ export class Pod extends WorkloadKubeObject { } getNodeName() { - return this.spec?.nodeName + return this.spec?.nodeName; } getSelectedNodeOs() { - if (!this.spec.nodeSelector) return - if (!this.spec.nodeSelector["kubernetes.io/os"] && !this.spec.nodeSelector["beta.kubernetes.io/os"]) return + if (!this.spec.nodeSelector) return; + if (!this.spec.nodeSelector["kubernetes.io/os"] && !this.spec.nodeSelector["beta.kubernetes.io/os"]) return; - return this.spec.nodeSelector["kubernetes.io/os"] || this.spec.nodeSelector["beta.kubernetes.io/os"] + return this.spec.nodeSelector["kubernetes.io/os"] || this.spec.nodeSelector["beta.kubernetes.io/os"]; } } diff --git a/src/renderer/api/endpoints/podsecuritypolicy.api.ts b/src/renderer/api/endpoints/podsecuritypolicy.api.ts index aa705c8748..c7981f65be 100644 --- a/src/renderer/api/endpoints/podsecuritypolicy.api.ts +++ b/src/renderer/api/endpoints/podsecuritypolicy.api.ts @@ -4,9 +4,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class PodSecurityPolicy extends KubeObject { - static kind = "PodSecurityPolicy" - static namespaced = false - static apiBase = "/apis/policy/v1beta1/podsecuritypolicies" + static kind = "PodSecurityPolicy"; + static namespaced = false; + static apiBase = "/apis/policy/v1beta1/podsecuritypolicies"; spec: { allowPrivilegeEscalation?: boolean; @@ -66,7 +66,7 @@ export class PodSecurityPolicy extends KubeObject { ranges: { max: number; min: number }[]; }; volumes?: string[]; - } + }; isPrivileged() { return !!this.spec.privileged; diff --git a/src/renderer/api/endpoints/replica-set.api.ts b/src/renderer/api/endpoints/replica-set.api.ts index dd06299644..d1081811e9 100644 --- a/src/renderer/api/endpoints/replica-set.api.ts +++ b/src/renderer/api/endpoints/replica-set.api.ts @@ -6,9 +6,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class ReplicaSet extends WorkloadKubeObject { - static kind = "ReplicaSet" - static namespaced = true - static apiBase = "/apis/apps/v1/replicasets" + static kind = "ReplicaSet"; + static namespaced = true; + static apiBase = "/apis/apps/v1/replicasets"; spec: { replicas?: number; @@ -37,18 +37,18 @@ export class ReplicaSet extends WorkloadKubeObject { terminationGracePeriodSeconds?: number; dnsPolicy?: string; schedulerName?: string; - } + }; status: { replicas: number; fullyLabeledReplicas: number; readyReplicas: number; availableReplicas: number; observedGeneration: number; - } + }; getImages() { - const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []) - return [...containers].map(container => container.image) + const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []); + return [...containers].map(container => container.image); } } diff --git a/src/renderer/api/endpoints/resource-applier.api.ts b/src/renderer/api/endpoints/resource-applier.api.ts index 088c7ed8f2..a2843a6262 100644 --- a/src/renderer/api/endpoints/resource-applier.api.ts +++ b/src/renderer/api/endpoints/resource-applier.api.ts @@ -1,4 +1,4 @@ -import jsYaml from "js-yaml" +import jsYaml from "js-yaml"; import { KubeObject } from "../kube-object"; import { KubeJsonApiData } from "../kube-json-api"; import { apiBase } from "../index"; @@ -21,7 +21,7 @@ export const resourceApplierApi = { if (api) { return new api.objectConstructor(obj); } else { - return new KubeObject(obj) + return new KubeObject(obj); } }); return items.length === 1 ? items[0] : items; diff --git a/src/renderer/api/endpoints/resource-quota.api.ts b/src/renderer/api/endpoints/resource-quota.api.ts index ce73d24595..a19e4025c5 100644 --- a/src/renderer/api/endpoints/resource-quota.api.ts +++ b/src/renderer/api/endpoints/resource-quota.api.ts @@ -31,13 +31,13 @@ export interface IResourceQuotaValues { } export class ResourceQuota extends KubeObject { - static kind = "ResourceQuota" - static namespaced = true - static apiBase = "/api/v1/resourcequotas" + static kind = "ResourceQuota"; + static namespaced = true; + static apiBase = "/api/v1/resourcequotas"; constructor(data: KubeJsonApiData) { super(data); - this.spec = this.spec || {} as any + this.spec = this.spec || {} as any; } spec: { @@ -49,12 +49,12 @@ export class ResourceQuota extends KubeObject { values: string[]; }[]; }; - } + }; status: { hard: IResourceQuotaValues; used: IResourceQuotaValues; - } + }; getScopeSelector() { const { matchExpressions = [] } = this.spec.scopeSelector || {}; diff --git a/src/renderer/api/endpoints/role-binding.api.ts b/src/renderer/api/endpoints/role-binding.api.ts index 455e2c6e4d..866656ee56 100644 --- a/src/renderer/api/endpoints/role-binding.api.ts +++ b/src/renderer/api/endpoints/role-binding.api.ts @@ -11,23 +11,23 @@ export interface IRoleBindingSubject { @autobind() export class RoleBinding extends KubeObject { - static kind = "RoleBinding" - static namespaced = true - static apiBase = "/apis/rbac.authorization.k8s.io/v1/rolebindings" + static kind = "RoleBinding"; + static namespaced = true; + static apiBase = "/apis/rbac.authorization.k8s.io/v1/rolebindings"; - subjects?: IRoleBindingSubject[] + subjects?: IRoleBindingSubject[]; roleRef: { kind: string; name: string; apiGroup?: string; - } + }; getSubjects() { return this.subjects || []; } getSubjectNames(): string { - return this.getSubjects().map(subject => subject.name).join(", ") + return this.getSubjects().map(subject => subject.name).join(", "); } } diff --git a/src/renderer/api/endpoints/role.api.ts b/src/renderer/api/endpoints/role.api.ts index 400761cfbe..c89834ed05 100644 --- a/src/renderer/api/endpoints/role.api.ts +++ b/src/renderer/api/endpoints/role.api.ts @@ -2,16 +2,16 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; export class Role extends KubeObject { - static kind = "Role" - static namespaced = true - static apiBase = "/apis/rbac.authorization.k8s.io/v1/roles" + static kind = "Role"; + static namespaced = true; + static apiBase = "/apis/rbac.authorization.k8s.io/v1/roles"; rules: { verbs: string[]; apiGroups: string[]; resources: string[]; resourceNames?: string[]; - }[] + }[]; getRules() { return this.rules || []; diff --git a/src/renderer/api/endpoints/secret.api.ts b/src/renderer/api/endpoints/secret.api.ts index f2166abbe1..16262570df 100644 --- a/src/renderer/api/endpoints/secret.api.ts +++ b/src/renderer/api/endpoints/secret.api.ts @@ -21,15 +21,15 @@ export interface ISecretRef { @autobind() export class Secret extends KubeObject { - static kind = "Secret" - static namespaced = true - static apiBase = "/api/v1/secrets" + static kind = "Secret"; + static namespaced = true; + static apiBase = "/api/v1/secrets"; type: SecretType; data: { [prop: string]: string; token?: string; - } + }; constructor(data: KubeJsonApiData) { super(data); diff --git a/src/renderer/api/endpoints/selfsubjectrulesreviews.api.ts b/src/renderer/api/endpoints/selfsubjectrulesreviews.api.ts index 1beece3fc3..149a94e678 100644 --- a/src/renderer/api/endpoints/selfsubjectrulesreviews.api.ts +++ b/src/renderer/api/endpoints/selfsubjectrulesreviews.api.ts @@ -21,20 +21,20 @@ export interface ISelfSubjectReviewRule { } export class SelfSubjectRulesReview extends KubeObject { - static kind = "SelfSubjectRulesReview" - static namespaced = false - static apiBase = "/apis/authorization.k8s.io/v1/selfsubjectrulesreviews" + static kind = "SelfSubjectRulesReview"; + static namespaced = false; + static apiBase = "/apis/authorization.k8s.io/v1/selfsubjectrulesreviews"; spec: { // todo: add more types from api docs namespace?: string; - } + }; status: { resourceRules: ISelfSubjectReviewRule[]; nonResourceRules: ISelfSubjectReviewRule[]; incomplete: boolean; - } + }; getResourceRules() { const rules = this.status && this.status.resourceRules || []; @@ -58,7 +58,7 @@ export class SelfSubjectRulesReview extends KubeObject { const separator = apiGroup == "" ? "" : "."; return resource + separator + apiGroup; }) - } + }; } } diff --git a/src/renderer/api/endpoints/service-accounts.api.ts b/src/renderer/api/endpoints/service-accounts.api.ts index 4f3ae47014..9f449cdec4 100644 --- a/src/renderer/api/endpoints/service-accounts.api.ts +++ b/src/renderer/api/endpoints/service-accounts.api.ts @@ -6,14 +6,14 @@ import { KubeApi } from "../kube-api"; export class ServiceAccount extends KubeObject { static kind = "ServiceAccount"; static namespaced = true; - static apiBase = "/api/v1/serviceaccounts" + static apiBase = "/api/v1/serviceaccounts"; secrets?: { name: string; - }[] + }[]; imagePullSecrets?: { name: string; - }[] + }[]; getSecrets() { return this.secrets || []; diff --git a/src/renderer/api/endpoints/service.api.ts b/src/renderer/api/endpoints/service.api.ts index 49ac733220..5524e85263 100644 --- a/src/renderer/api/endpoints/service.api.ts +++ b/src/renderer/api/endpoints/service.api.ts @@ -17,7 +17,7 @@ export class ServicePort implements IServicePort { nodePort?: number; constructor(data: IServicePort) { - Object.assign(this, data) + Object.assign(this, data); } toString() { @@ -31,9 +31,9 @@ export class ServicePort implements IServicePort { @autobind() export class Service extends KubeObject { - static kind = "Service" - static namespaced = true - static apiBase = "/api/v1/services" + static kind = "Service"; + static namespaced = true; + static apiBase = "/api/v1/services"; spec: { type: string; @@ -44,7 +44,7 @@ export class Service extends KubeObject { selector: { [key: string]: string }; ports: ServicePort[]; externalIPs?: string[]; // https://kubernetes.io/docs/concepts/services-networking/service/#external-ips - } + }; status: { loadBalancer?: { @@ -53,7 +53,7 @@ export class Service extends KubeObject { hostname?: string; }[]; }; - } + }; getClusterIp() { return this.spec.clusterIP; @@ -62,7 +62,7 @@ export class Service extends KubeObject { getExternalIps() { const lb = this.getLoadBalancer(); if (lb && lb.ingress) { - return lb.ingress.map(val => val.ip || val.hostname) + return lb.ingress.map(val => val.ip || val.hostname); } return this.spec.externalIPs || []; } diff --git a/src/renderer/api/endpoints/stateful-set.api.ts b/src/renderer/api/endpoints/stateful-set.api.ts index c507e7df59..6a6f8c151d 100644 --- a/src/renderer/api/endpoints/stateful-set.api.ts +++ b/src/renderer/api/endpoints/stateful-set.api.ts @@ -6,9 +6,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class StatefulSet extends WorkloadKubeObject { - static kind = "StatefulSet" - static namespaced = true - static apiBase = "/apis/apps/v1/statefulsets" + static kind = "StatefulSet"; + static namespaced = true; + static apiBase = "/apis/apps/v1/statefulsets"; spec: { serviceName: string; @@ -62,7 +62,7 @@ export class StatefulSet extends WorkloadKubeObject { }; }; }[]; - } + }; status: { observedGeneration: number; replicas: number; @@ -70,11 +70,11 @@ export class StatefulSet extends WorkloadKubeObject { currentRevision: string; updateRevision: string; collisionCount: number; - } + }; getImages() { - const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []) - return [...containers].map(container => container.image) + const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []); + return [...containers].map(container => container.image); } } diff --git a/src/renderer/api/endpoints/storage-class.api.ts b/src/renderer/api/endpoints/storage-class.api.ts index cf05e13eaf..adb2059e4a 100644 --- a/src/renderer/api/endpoints/storage-class.api.ts +++ b/src/renderer/api/endpoints/storage-class.api.ts @@ -4,9 +4,9 @@ import { KubeApi } from "../kube-api"; @autobind() export class StorageClass extends KubeObject { - static kind = "StorageClass" - static namespaced = false - static apiBase = "/apis/storage.k8s.io/v1/storageclasses" + static kind = "StorageClass"; + static namespaced = false; + static apiBase = "/apis/storage.k8s.io/v1/storageclasses"; provisioner: string; // e.g. "storage.k8s.io/v1" mountOptions?: string[]; @@ -14,22 +14,22 @@ export class StorageClass extends KubeObject { reclaimPolicy: string; parameters: { [param: string]: string; // every provisioner has own set of these parameters - } + }; isDefault() { const annotations = this.metadata.annotations || {}; return ( annotations["storageclass.kubernetes.io/is-default-class"] === "true" || annotations["storageclass.beta.kubernetes.io/is-default-class"] === "true" - ) + ); } getVolumeBindingMode() { - return this.volumeBindingMode || "-" + return this.volumeBindingMode || "-"; } getReclaimPolicy() { - return this.reclaimPolicy || "-" + return this.reclaimPolicy || "-"; } } diff --git a/src/renderer/api/json-api.ts b/src/renderer/api/json-api.ts index e42996c041..cc239a804e 100644 --- a/src/renderer/api/json-api.ts +++ b/src/renderer/api/json-api.ts @@ -110,23 +110,23 @@ export class JsonApi { } else { const error = new JsonApiErrorParsed(data, this.parseError(data, res)); this.onError.emit(error, res); - this.writeLog({ ...log, error }) + this.writeLog({ ...log, error }); throw error; } - }) + }); } protected parseError(error: JsonApiError | string, res: Response): string[] { if (typeof error === "string") { - return [error] + return [error]; } else if (Array.isArray(error.errors)) { - return error.errors.map(error => error.title) + return error.errors.map(error => error.title); } else if (error.message) { - return [error.message] + return [error.message]; } - return [res.statusText || "Error!"] + return [res.statusText || "Error!"]; } protected writeLog(log: JsonApiLog) { diff --git a/src/renderer/api/kube-api-parse.ts b/src/renderer/api/kube-api-parse.ts index c4c93562cf..0995fac24f 100644 --- a/src/renderer/api/kube-api-parse.ts +++ b/src/renderer/api/kube-api-parse.ts @@ -51,7 +51,7 @@ export function parseKubeApi(path: string): IKubeApiParsed { } else { switch (left.length) { case 4: - [apiGroup, apiVersion, resource, name] = left + [apiGroup, apiVersion, resource, name] = left; break; case 2: resource = left.pop(); @@ -79,11 +79,11 @@ export function parseKubeApi(path: string): IKubeApiParsed { */ if (left[0].includes('.') || left[1].match(/^v[0-9]/)) { [apiGroup, apiVersion] = left; - resource = left.slice(2).join("/") + resource = left.slice(2).join("/"); } else { apiGroup = ""; apiVersion = left[0]; - [resource, name] = left.slice(1) + [resource, name] = left.slice(1); } break; } @@ -93,7 +93,7 @@ export function parseKubeApi(path: string): IKubeApiParsed { const apiBase = [apiPrefix, apiGroup, apiVersion, resource].filter(v => v).join("/"); if (!apiBase) { - throw new Error(`invalid apiPath: ${path}`) + throw new Error(`invalid apiPath: ${path}`); } return { @@ -108,11 +108,11 @@ export function createKubeApiURL(ref: IKubeApiLinkRef): string { const { apiPrefix = "/apis", resource, apiVersion, name } = ref; let { namespace } = ref; if (namespace) { - namespace = `namespaces/${namespace}` + namespace = `namespaces/${namespace}`; } return [apiPrefix, apiVersion, namespace, resource, name] .filter(v => v) - .join("/") + .join("/"); } export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string { @@ -124,9 +124,9 @@ export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): st if (!kind) return ""; // search in registered apis by 'kind' & 'apiVersion' - const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion) + const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion); if (api) { - return api.getUrl({ namespace, name }) + return api.getUrl({ namespace, name }); } // lookup api by generated resource link @@ -142,10 +142,10 @@ export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): st // resolve by kind only (hpa's might use refs to older versions of resources for example) const apiByKind = apiManager.getApi(api => api.kind === kind); if (apiByKind) { - return apiByKind.getUrl({ name, namespace }) + return apiByKind.getUrl({ name, namespace }); } // otherwise generate link with default prefix // resource still might exists in k8s, but api is not registered in the app - return createKubeApiURL({ apiVersion, name, namespace, resource }) + return createKubeApiURL({ apiVersion, name, namespace, resource }); } diff --git a/src/renderer/api/kube-api.ts b/src/renderer/api/kube-api.ts index c3c9698cfa..d4840d3620 100644 --- a/src/renderer/api/kube-api.ts +++ b/src/renderer/api/kube-api.ts @@ -1,6 +1,6 @@ // Base class for building all kubernetes apis -import merge from "lodash/merge" +import merge from "lodash/merge"; import { stringify } from "querystring"; import { IKubeObjectConstructor, KubeObject } from "./kube-object"; import { KubeJsonApi, KubeJsonApiData, KubeJsonApiDataList } from "./kube-json-api"; @@ -51,7 +51,7 @@ export function forCluster(cluster: IKubeApiCluster, kubeC return new KubeApi({ objectConstructor: kubeClass, request: request - }) + }); } export class KubeApi { @@ -62,14 +62,14 @@ export class KubeApi { return () => disposers.forEach(unwatch => unwatch()); } - readonly kind: string - readonly apiBase: string - readonly apiPrefix: string - readonly apiGroup: string - readonly apiVersion: string + readonly kind: string; + readonly apiBase: string; + readonly apiPrefix: string; + readonly apiGroup: string; + readonly apiVersion: string; readonly apiVersionPreferred?: string; - readonly apiResource: string - readonly isNamespaced: boolean + readonly apiResource: string; + readonly isNamespaced: boolean; public objectConstructor: IKubeObjectConstructor; protected request: KubeJsonApi; @@ -83,7 +83,7 @@ export class KubeApi { isNamespaced = options.objectConstructor?.namespaced } = options || {}; if (!options.apiBase) { - options.apiBase = objectConstructor.apiBase + options.apiBase = objectConstructor.apiBase; } const { apiBase, apiPrefix, apiGroup, apiVersion, apiVersionWithGroup, resource } = KubeApi.parseApi(options.apiBase); @@ -105,7 +105,7 @@ export class KubeApi { get apiVersionWithGroup() { return [this.apiGroup, this.apiVersionPreferred ?? this.apiVersion] .filter(Boolean) - .join("/") + .join("/"); } protected async checkPreferredVersion() { @@ -116,7 +116,7 @@ export class KubeApi { }); if (this.apiVersionPreferred) { - Object.defineProperty(this, "apiBase", { value: this.getUrl() }) + Object.defineProperty(this, "apiBase", { value: this.getUrl() }); apiManager.registerApi(this.apiBase, this); } } @@ -147,10 +147,10 @@ export class KubeApi { protected normalizeQuery(query: Partial = {}) { if (query.labelSelector) { - query.labelSelector = [query.labelSelector].flat().join(",") + query.labelSelector = [query.labelSelector].flat().join(","); } if (query.fieldSelector) { - query.fieldSelector = [query.fieldSelector].flat().join(",") + query.fieldSelector = [query.fieldSelector].flat().join(","); } return query; } @@ -170,7 +170,7 @@ export class KubeApi { kind: this.kind, apiVersion: apiVersion, ...item, - })) + })); } // custom apis might return array for list response, e.g. users, groups, etc. @@ -218,13 +218,13 @@ export class KubeApi { const apiUrl = this.getUrl({ namespace, name }); return this.request .put(apiUrl, { data }) - .then(this.parseResponse) + .then(this.parseResponse); } async delete({ name = "", namespace = "default" }) { await this.checkPreferredVersion(); const apiUrl = this.getUrl({ namespace, name }); - return this.request.del(apiUrl) + return this.request.del(apiUrl); } getWatchUrl(namespace = "", query: IKubeApiQueryParams = {}) { @@ -232,7 +232,7 @@ export class KubeApi { watch: 1, resourceVersion: this.getResourceVersion(namespace), ...query, - }) + }); } watch(): () => void { @@ -240,4 +240,4 @@ export class KubeApi { } } -export * from "./kube-api-parse" +export * from "./kube-api-parse"; diff --git a/src/renderer/api/kube-object-detail-registry.ts b/src/renderer/api/kube-object-detail-registry.ts index f844da9ef3..5246254532 100644 --- a/src/renderer/api/kube-object-detail-registry.ts +++ b/src/renderer/api/kube-object-detail-registry.ts @@ -1 +1 @@ -export { kubeObjectDetailRegistry } from "../../extensions/registries/kube-object-detail-registry" +export { kubeObjectDetailRegistry } from "../../extensions/registries/kube-object-detail-registry"; diff --git a/src/renderer/api/kube-object.ts b/src/renderer/api/kube-object.ts index 664f9a5c22..8d0e6123f3 100644 --- a/src/renderer/api/kube-object.ts +++ b/src/renderer/api/kube-object.ts @@ -65,20 +65,20 @@ export class KubeObject implements ItemObject { static stringifyLabels(labels: { [name: string]: string }): string[] { if (!labels) return []; - return Object.entries(labels).map(([name, value]) => `${name}=${value}`) + return Object.entries(labels).map(([name, value]) => `${name}=${value}`); } constructor(data: KubeJsonApiData) { Object.assign(this, data); } - apiVersion: string - kind: string + apiVersion: string; + kind: string; metadata: IKubeObjectMetadata; status?: any; // todo: type-safety support get selfLink() { - return this.metadata.selfLink + return this.metadata.selfLink; } getId() { @@ -131,18 +131,18 @@ export class KubeObject implements ItemObject { return refs.map(ownerRef => ({ ...ownerRef, namespace: this.getNs(), - })) + })); } getSearchFields() { - const { getName, getId, getNs, getAnnotations, getLabels } = this + const { getName, getId, getNs, getAnnotations, getLabels } = this; return [ getName(), getNs(), getId(), ...getLabels(), ...getAnnotations(true), - ] + ]; } toPlainObject(): object { diff --git a/src/renderer/api/kube-watch-api.ts b/src/renderer/api/kube-watch-api.ts index 56c3fc1c86..8ce44fb77c 100644 --- a/src/renderer/api/kube-watch-api.ts +++ b/src/renderer/api/kube-watch-api.ts @@ -1,7 +1,7 @@ // Kubernetes watch-api consumer import { computed, observable, reaction } from "mobx"; -import { stringify } from "querystring" +import { stringify } from "querystring"; import { autobind, EventEmitter } from "../utils"; import { KubeJsonApiData } from "./kube-json-api"; import type { KubeObjectStore } from "../kube-object.store"; @@ -61,13 +61,13 @@ export class KubeWatchApi { } protected getQuery(): Partial { - const { isAdmin, allowedNamespaces } = getHostedCluster() + const { isAdmin, allowedNamespaces } = getHostedCluster(); return { api: this.activeApis.map(api => { if (isAdmin) return api.getWatchUrl(); - return allowedNamespaces.map(namespace => api.getWatchUrl(namespace)) + return allowedNamespaces.map(namespace => api.getWatchUrl(namespace)); }).flat() - } + }; } // todo: maybe switch to websocket to avoid often reconnects @@ -119,11 +119,11 @@ export class KubeWatchApi { await api.refreshResourceVersion({ namespace }); this.reconnect(); } catch (error) { - console.error("failed to refresh resource version", error) + console.error("failed to refresh resource version", error); if (this.subscribers.size > 0) { setTimeout(() => { - this.onRouteEvent(event) - }, 1000) + this.onRouteEvent(event); + }, 1000); } } } diff --git a/src/renderer/api/terminal-api.ts b/src/renderer/api/terminal-api.ts index 0e8bba2df6..4f66544f86 100644 --- a/src/renderer/api/terminal-api.ts +++ b/src/renderer/api/terminal-api.ts @@ -1,7 +1,7 @@ import { stringify } from "querystring"; import { autobind, base64, EventEmitter } from "../utils"; import { WebSocketApi } from "./websocket-api"; -import isEqual from "lodash/isEqual" +import isEqual from "lodash/isEqual"; import { isDevelopment } from "../../common/vars"; export enum TerminalChannels { @@ -28,7 +28,7 @@ export type TerminalApiQuery = Record & { id: string; node?: string; type?: string | "node"; -} +}; export class TerminalApi extends WebSocketApi { protected size: { Width: number; Height: number }; @@ -51,7 +51,7 @@ export class TerminalApi extends WebSocketApi { const wss = `ws${protocol === "https:" ? "s" : ""}://`; const query: TerminalApiQuery = { id }; if (port) { - port = `:${port}` + port = `:${port}`; } if (node) { query.node = node; diff --git a/src/renderer/api/websocket-api.ts b/src/renderer/api/websocket-api.ts index cb94881035..934d6cded6 100644 --- a/src/renderer/api/websocket-api.ts +++ b/src/renderer/api/websocket-api.ts @@ -146,7 +146,7 @@ export class WebSocketApi { } 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) { diff --git a/src/renderer/api/workload-kube-object.ts b/src/renderer/api/workload-kube-object.ts index c18b8df6c4..51c0461f15 100644 --- a/src/renderer/api/workload-kube-object.ts +++ b/src/renderer/api/workload-kube-object.ts @@ -65,16 +65,16 @@ export class WorkloadKubeObject extends KubeObject { } getTolerations(): IToleration[] { - return get(this, "spec.template.spec.tolerations", []) + return get(this, "spec.template.spec.tolerations", []); } getAffinity(): IAffinity { - return get(this, "spec.template.spec.affinity") + return get(this, "spec.template.spec.affinity"); } getAffinityNumber() { - const affinity = this.getAffinity() - if (!affinity) return 0 - return Object.keys(affinity).length + const affinity = this.getAffinity(); + if (!affinity) return 0; + return Object.keys(affinity).length; } } \ No newline at end of file diff --git a/src/renderer/bootstrap.tsx b/src/renderer/bootstrap.tsx index cfadb5c379..7aa78f1682 100644 --- a/src/renderer/bootstrap.tsx +++ b/src/renderer/bootstrap.tsx @@ -1,9 +1,9 @@ -import "./components/app.scss" +import "./components/app.scss"; import React from "react"; -import * as Mobx from "mobx" -import * as MobxReact from "mobx-react" -import * as LensExtensions from "../extensions/extension-api" +import * as Mobx from "mobx"; +import * as MobxReact from "mobx-react"; +import * as LensExtensions from "../extensions/extension-api"; import { App } from "./components/app"; import { LensApp } from "./lens-app"; import { render, unmountComponentAtNode } from "react-dom"; @@ -18,20 +18,20 @@ import { extensionLoader } from "../extensions/extension-loader"; type AppComponent = React.ComponentType & { init?(): Promise; -} +}; export { React, Mobx, MobxReact, LensExtensions -} +}; export async function bootstrap(App: AppComponent) { - const rootElem = document.getElementById("app") + const rootElem = document.getElementById("app"); rootElem.classList.toggle("is-mac", isMac); - extensionLoader.init() + extensionLoader.init(); // preload common stores await Promise.all([ @@ -53,13 +53,13 @@ export async function bootstrap(App: AppComponent) { } window.addEventListener("message", (ev: MessageEvent) => { if (ev.data === "teardown") { - userStore.unregisterIpcListener() - workspaceStore.unregisterIpcListener() - clusterStore.unregisterIpcListener() - unmountComponentAtNode(rootElem) - window.location.href = "about:blank" + userStore.unregisterIpcListener(); + workspaceStore.unregisterIpcListener(); + clusterStore.unregisterIpcListener(); + unmountComponentAtNode(rootElem); + window.location.href = "about:blank"; } - }) + }); render(<> {isMac &&

} diff --git a/src/renderer/components/+404/index.ts b/src/renderer/components/+404/index.ts index 7314f53562..67433b02c3 100644 --- a/src/renderer/components/+404/index.ts +++ b/src/renderer/components/+404/index.ts @@ -1 +1 @@ -export * from "./not-found" +export * from "./not-found"; diff --git a/src/renderer/components/+add-cluster/add-cluster.route.ts b/src/renderer/components/+add-cluster/add-cluster.route.ts index ba3ffcd104..3f1e36be9e 100644 --- a/src/renderer/components/+add-cluster/add-cluster.route.ts +++ b/src/renderer/components/+add-cluster/add-cluster.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const addClusterRoute: RouteProps = { path: "/add-cluster" -} +}; -export const addClusterURL = buildURL(addClusterRoute.path) +export const addClusterURL = buildURL(addClusterRoute.path); diff --git a/src/renderer/components/+add-cluster/add-cluster.tsx b/src/renderer/components/+add-cluster/add-cluster.tsx index 8acd3a51ea..abb28d090e 100644 --- a/src/renderer/components/+add-cluster/add-cluster.tsx +++ b/src/renderer/components/+add-cluster/add-cluster.tsx @@ -1,4 +1,4 @@ -import "./add-cluster.scss" +import "./add-cluster.scss"; import os from "os"; import React, { Fragment } from "react"; import { observer } from "mobx-react"; @@ -16,7 +16,7 @@ import { WizardLayout } from "../layout/wizard-layout"; import { kubeConfigDefaultPath, loadConfig, splitConfig, validateConfig, validateKubeConfig } from "../../../common/kube-helpers"; import { ClusterModel, ClusterStore, clusterStore } from "../../../common/cluster-store"; import { workspaceStore } from "../../../common/workspace-store"; -import { v4 as uuid } from "uuid" +import { v4 as uuid } from "uuid"; import { navigate } from "../../navigation"; import { userStore } from "../../../common/user-store"; import { clusterViewURL } from "../cluster-manager/cluster-view.route"; @@ -39,10 +39,10 @@ export class AddCluster extends React.Component { @observable selectedContexts = observable.array(); @observable sourceTab = KubeConfigSourceTab.FILE; @observable kubeConfigPath = ""; - @observable customConfig = "" - @observable proxyServer = "" - @observable isWaiting = false - @observable showSettings = false + @observable customConfig = ""; + @observable proxyServer = ""; + @observable isWaiting = false; + @observable showSettings = false; @observable dropAreaActive = false; componentDidMount() { @@ -84,7 +84,7 @@ export class AddCluster extends React.Component { break; case KubeConfigSourceTab.TEXT: try { - this.error = "" + this.error = ""; const contexts = this.getContexts(loadConfig(this.customConfig || "{}")); this.kubeContexts.replace(contexts); } catch (err) { @@ -94,7 +94,7 @@ export class AddCluster extends React.Component { } if (this.kubeContexts.size === 1) { - this.selectedContexts.push(this.kubeContexts.keys().next().value) + this.selectedContexts.push(this.kubeContexts.keys().next().value); } } @@ -102,8 +102,8 @@ export class AddCluster extends React.Component { const contexts = new Map(); splitConfig(config).forEach(config => { contexts.set(config.currentContext, config); - }) - return contexts + }); + return contexts; } selectKubeConfigDialog = async () => { @@ -117,18 +117,18 @@ export class AddCluster extends React.Component { if (!canceled && filePaths.length) { this.setKubeConfig(filePaths[0]); } - } + }; @action addClusters = () => { let newClusters: ClusterModel[] = []; try { if (!this.selectedContexts.length) { - this.error = Please select at least one cluster context + this.error = Please select at least one cluster context; return; } - this.error = "" - this.isWaiting = true + this.error = ""; + this.isWaiting = true; newClusters = this.selectedContexts.filter(context => { try { @@ -136,7 +136,7 @@ export class AddCluster extends React.Component { validateKubeConfig(kubeConfig); return true; } catch (err) { - this.error = String(err.message) + this.error = String(err.message); if (err instanceof ExecValidationNotFoundError ) { Notifications.error(Error while adding cluster(s): {this.error}); return false; @@ -159,8 +159,8 @@ export class AddCluster extends React.Component { clusterName: kubeConfig.currentContext, httpsProxy: this.proxyServer || undefined, }, - } - }) + }; + }); runInAction(() => { clusterStore.addClusters(...newClusters); @@ -175,7 +175,7 @@ export class AddCluster extends React.Component { ); } } - }) + }); this.refreshContexts(); } catch (err) { this.error = String(err); @@ -183,7 +183,7 @@ export class AddCluster extends React.Component { } finally { this.isWaiting = false; } - } + }; renderInfo() { return ( @@ -218,7 +218,7 @@ export class AddCluster extends React.Component { Lens app might not have all login shell env variables set automatically.

- ) + ); } renderKubeConfigSource() { @@ -281,7 +281,7 @@ export class AddCluster extends React.Component { )} - ) + ); } renderContextSelector() { @@ -302,7 +302,7 @@ export class AddCluster extends React.Component { noOptionsMessage={() => _i18n._(t`No contexts available or they have been added already`)} onChange={({ value: ctx }: SelectOption) => { if (this.selectedContexts.includes(ctx)) { - this.selectedContexts.remove(ctx) + this.selectedContexts.remove(ctx); } else { this.selectedContexts.push(ctx); } @@ -315,7 +315,7 @@ export class AddCluster extends React.Component { )} - ) + ); } onKubeConfigInputBlur = (evt: React.FocusEvent) => { @@ -328,13 +328,13 @@ export class AddCluster extends React.Component { this.setKubeConfig(userStore.kubeConfigPath); // revert to previous valid path } } - } + }; onKubeConfigTabChange = (tabId: KubeConfigSourceTab) => { this.sourceTab = tabId; this.error = ""; this.refreshContexts(); - } + }; protected formatContextLabel = ({ value: context }: SelectOption) => { const isNew = userStore.newContexts.has(context); @@ -345,11 +345,11 @@ export class AddCluster extends React.Component { {isNew && } {isSelected && }
- ) + ); }; render() { - const addDisabled = this.selectedContexts.length === 0 + const addDisabled = this.selectedContexts.length === 0; return ( this.dropAreaActive = false, onDragOver: event => { event.preventDefault(); // enable onDrop()-callback - event.dataTransfer.dropEffect = "move" + event.dataTransfer.dropEffect = "move"; }, onDrop: event => { this.sourceTab = KubeConfigSourceTab.FILE; - this.dropAreaActive = false - this.setKubeConfig(event.dataTransfer.files[0].path) + this.dropAreaActive = false; + this.setKubeConfig(event.dataTransfer.files[0].path); } }} > @@ -407,6 +407,6 @@ export class AddCluster extends React.Component { /> - ) + ); } } diff --git a/src/renderer/components/+add-cluster/index.ts b/src/renderer/components/+add-cluster/index.ts index 42ab8bf944..1ddb3d069d 100644 --- a/src/renderer/components/+add-cluster/index.ts +++ b/src/renderer/components/+add-cluster/index.ts @@ -1,2 +1,2 @@ -export * from "./add-cluster" -export * from "./add-cluster.route" +export * from "./add-cluster"; +export * from "./add-cluster.route"; diff --git a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx index a5531affa3..a446c4dd52 100644 --- a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx +++ b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx @@ -35,16 +35,16 @@ export class HelmChartDetails extends Component { } chartUpdater = autorun(() => { - this.selectedChart = null - const { chart: { name, repo, version } } = this.props + this.selectedChart = null; + const { chart: { name, repo, version } } = this.props; helmChartsApi.get(repo, name, version).then(result => { - this.readme = result.readme - this.chartVersions = result.versions - this.selectedChart = result.versions[0] + this.readme = result.readme; + this.chartVersions = result.versions; + this.selectedChart = result.versions[0]; }, error => { this.error = error; - }) + }); }); @autobind() @@ -55,7 +55,7 @@ export class HelmChartDetails extends Component { try { this.chartPromise?.cancel(); const { chart: { name, repo } } = this.props; - const { readme } = await (this.chartPromise = helmChartsApi.get(repo, name, version)) + const { readme } = await (this.chartPromise = helmChartsApi.get(repo, name, version)); this.readme = readme; } catch (error) { this.error = error; @@ -65,7 +65,7 @@ export class HelmChartDetails extends Component { @autobind() install() { createInstallChartTab(this.selectedChart); - this.props.hideDetails() + this.props.hideDetails(); } renderIntroduction() { @@ -112,14 +112,14 @@ export class HelmChartDetails extends Component { renderReadme() { if (this.readme === null) { - return + return ; } return (
- ) + ); } renderContent() { @@ -132,7 +132,7 @@ export class HelmChartDetails extends Component {

{this.error}

- ) + ); } return ( diff --git a/src/renderer/components/+apps-helm-charts/helm-chart.store.ts b/src/renderer/components/+apps-helm-charts/helm-chart.store.ts index 1d231c08dd..65e73b556f 100644 --- a/src/renderer/components/+apps-helm-charts/helm-chart.store.ts +++ b/src/renderer/components/+apps-helm-charts/helm-chart.store.ts @@ -1,9 +1,9 @@ -import semver from "semver" +import semver from "semver"; import { observable } from "mobx"; import { autobind } from "../../utils"; import { HelmChart, helmChartsApi } from "../../api/endpoints/helm-charts.api"; import { ItemStore } from "../../item.store"; -import flatten from "lodash/flatten" +import flatten from "lodash/flatten"; export interface IChartVersion { repo: string; @@ -24,7 +24,7 @@ export class HelmChartStore extends ItemStore { protected sortVersions = (versions: IChartVersion[]) => { return versions.sort((first, second) => { - return semver.compare(second.version, first.version) + return semver.compare(second.version, first.version); }); }; @@ -38,8 +38,8 @@ export class HelmChartStore extends ItemStore { return versions.map(chart => ({ repo: repo, version: chart.getVersion() - })) - }) + })); + }); }; if (!this.isLoaded) { await this.loadAll(); diff --git a/src/renderer/components/+apps-helm-charts/helm-charts.route.ts b/src/renderer/components/+apps-helm-charts/helm-charts.route.ts index 047ff656b6..abd0677de8 100644 --- a/src/renderer/components/+apps-helm-charts/helm-charts.route.ts +++ b/src/renderer/components/+apps-helm-charts/helm-charts.route.ts @@ -4,11 +4,11 @@ import { appsRoute } from "../+apps/apps.route"; export const helmChartsRoute: RouteProps = { path: appsRoute.path + "/charts/:repo?/:chartName?" -} +}; export interface IHelmChartsRouteParams { chartName?: string; repo?: string; } -export const helmChartsURL = buildURL(helmChartsRoute.path) \ No newline at end of file +export const helmChartsURL = buildURL(helmChartsRoute.path); \ No newline at end of file diff --git a/src/renderer/components/+apps-helm-charts/helm-charts.tsx b/src/renderer/components/+apps-helm-charts/helm-charts.tsx index 473d78194e..c8b5312800 100644 --- a/src/renderer/components/+apps-helm-charts/helm-charts.tsx +++ b/src/renderer/components/+apps-helm-charts/helm-charts.tsx @@ -28,13 +28,13 @@ export class HelmCharts extends Component { } get selectedChart() { - const { match: { params: { chartName, repo } } } = this.props + const { match: { params: { chartName, repo } } } = this.props; return helmChartStore.getByName(chartName, repo); } showDetails = (chart: HelmChart) => { if (!chart) { - navigation.merge(helmChartsURL()) + navigation.merge(helmChartsURL()); } else { navigation.merge(helmChartsURL({ @@ -42,13 +42,13 @@ export class HelmCharts extends Component { chartName: chart.getName(), repo: chart.getRepository(), } - })) + })); } - } + }; hideDetails = () => { this.showDetails(null); - } + }; render() { return ( diff --git a/src/renderer/components/+apps-releases/release-details.tsx b/src/renderer/components/+apps-releases/release-details.tsx index cb7c7b8069..a27db5dc83 100644 --- a/src/renderer/components/+apps-releases/release-details.tsx +++ b/src/renderer/components/+apps-releases/release-details.tsx @@ -77,7 +77,7 @@ export class ReleaseDetails extends Component { updateValues = async () => { const { release } = this.props; const name = release.getName(); - const namespace = release.getNs() + const namespace = release.getNs(); const data = { chart: release.getChart(), repo: await release.getRepo(), @@ -94,13 +94,13 @@ export class ReleaseDetails extends Component { Notifications.error(err); } this.saving = false; - } + }; upgradeVersion = () => { const { release, hideDetails } = this.props; createUpgradeChartTab(release); hideDetails(); - } + }; renderValues() { const { values, saving } = this; @@ -121,7 +121,7 @@ export class ReleaseDetails extends Component { /> - ) + ); } renderNotes() { @@ -222,13 +222,13 @@ export class ReleaseDetails extends Component { {this.renderResources()} - ) + ); } render() { - const { release, hideDetails } = this.props - const title = release ? Release: {release.getName()} : "" - const toolbar = + const { release, hideDetails } = this.props; + const title = release ? Release: {release.getName()} : ""; + const toolbar = ; return ( { > {this.renderContent()} - ) + ); } } diff --git a/src/renderer/components/+apps-releases/release-menu.tsx b/src/renderer/components/+apps-releases/release-menu.tsx index 0bdb94edd2..aae3f34b79 100644 --- a/src/renderer/components/+apps-releases/release-menu.tsx +++ b/src/renderer/components/+apps-releases/release-menu.tsx @@ -46,7 +46,7 @@ export class HelmReleaseMenu extends React.Component { )} - ) + ); } render() { diff --git a/src/renderer/components/+apps-releases/release-rollback-dialog.tsx b/src/renderer/components/+apps-releases/release-rollback-dialog.tsx index 259394c2e1..f1c1841775 100644 --- a/src/renderer/components/+apps-releases/release-rollback-dialog.tsx +++ b/src/renderer/components/+apps-releases/release-rollback-dialog.tsx @@ -10,7 +10,7 @@ import { HelmRelease, helmReleasesApi, IReleaseRevision } from "../../api/endpoi import { releaseStore } from "./release.store"; import { Select, SelectOption } from "../select"; import { Notifications } from "../notifications"; -import orderBy from "lodash/orderBy" +import orderBy from "lodash/orderBy"; interface Props extends DialogProps { } @@ -46,7 +46,7 @@ export class ReleaseRollbackDialog extends React.Component { this.revisions.replace(releases); this.revision = this.revisions[0]; this.isLoading = false; - } + }; rollback = async () => { const revisionNumber = this.revision.revision; @@ -60,12 +60,12 @@ export class ReleaseRollbackDialog extends React.Component { close = () => { ReleaseRollbackDialog.close(); - } + }; renderContent() { const { revision, revisions } = this; if (!revision) { - return

No revisions to rollback.

+ return

No revisions to rollback.

; } return (
@@ -78,13 +78,13 @@ export class ReleaseRollbackDialog extends React.Component { onChange={({ value }: SelectOption) => this.revision = value} />
- ) + ); } render() { const { ...dialogProps } = this.props; const releaseName = this.release ? this.release.getName() : ""; - const header =
Rollback {releaseName}
+ const header =
Rollback {releaseName}
; return ( { - ) + ); } } diff --git a/src/renderer/components/+apps-releases/release.route.ts b/src/renderer/components/+apps-releases/release.route.ts index f874fefe67..a992383657 100644 --- a/src/renderer/components/+apps-releases/release.route.ts +++ b/src/renderer/components/+apps-releases/release.route.ts @@ -4,7 +4,7 @@ import { appsRoute } from "../+apps/apps.route"; export const releaseRoute: RouteProps = { path: appsRoute.path + "/releases/:namespace?/:name?" -} +}; export interface IReleaseRouteParams { name?: string; diff --git a/src/renderer/components/+apps-releases/release.store.ts b/src/renderer/components/+apps-releases/release.store.ts index 5120a63053..7fb438fd84 100644 --- a/src/renderer/components/+apps-releases/release.store.ts +++ b/src/renderer/components/+apps-releases/release.store.ts @@ -33,7 +33,7 @@ export class ReleaseStore extends ItemStore { this.loadAll(); } this.releaseSecrets = [...secrets]; - }) + }); } unwatch() { @@ -48,7 +48,7 @@ export class ReleaseStore extends ItemStore { const labels = { owner: "helm", name: release.getName() - } + }; return secretsStore.getByLabel(labels) .filter(secret => secret.getNs() == release.getNs())[0]; } @@ -58,7 +58,7 @@ export class ReleaseStore extends ItemStore { this.isLoading = true; let items; try { - const { isAdmin, allowedNamespaces } = getHostedCluster() + const { isAdmin, allowedNamespaces } = getHostedCluster(); items = await this.loadItems(!isAdmin ? allowedNamespaces : null); } finally { if (items) { diff --git a/src/renderer/components/+apps-releases/releases.tsx b/src/renderer/components/+apps-releases/releases.tsx index 234a812543..29dd11deb8 100644 --- a/src/renderer/components/+apps-releases/releases.tsx +++ b/src/renderer/components/+apps-releases/releases.tsx @@ -48,7 +48,7 @@ export class HelmReleases extends Component { showDetails = (item: HelmRelease) => { if (!item) { - navigation.merge(releaseURL()) + navigation.merge(releaseURL()); } else { navigation.merge(releaseURL({ @@ -56,13 +56,13 @@ export class HelmReleases extends Component { name: item.getName(), namespace: item.getNs() } - })) + })); } - } + }; hideDetails = () => { this.showDetails(null); - } + }; renderRemoveDialogMessage(selectedItems: HelmRelease[]) { const releaseNames = selectedItems.map(item => item.getName()).join(", "); @@ -73,7 +73,7 @@ export class HelmReleases extends Component { Note: StatefulSet Volumes won't be deleted automatically

- ) + ); } render() { @@ -122,7 +122,7 @@ export class HelmReleases extends Component { release.appVersion, { title: release.getStatus(), className: kebabCase(release.getStatus()) }, release.getUpdated(), - ] + ]; }} renderItemMenu={(release: HelmRelease) => { return ( @@ -130,7 +130,7 @@ export class HelmReleases extends Component { release={release} removeConfirmationMessage={this.renderRemoveDialogMessage([release])} /> - ) + ); }} customizeRemoveDialog={(selectedItems: HelmRelease[]) => ({ message: this.renderRemoveDialogMessage(selectedItems) diff --git a/src/renderer/components/+apps/apps.tsx b/src/renderer/components/+apps/apps.tsx index 469765aa68..537d2c3caf 100644 --- a/src/renderer/components/+apps/apps.tsx +++ b/src/renderer/components/+apps/apps.tsx @@ -23,12 +23,12 @@ export class Apps extends React.Component { url: releaseURL({ query }), routePath: releaseRoute.path.toString(), }, - ] + ]; } render() { return ( - ) + ); } } diff --git a/src/renderer/components/+cluster-settings/cluster-settings.route.ts b/src/renderer/components/+cluster-settings/cluster-settings.route.ts index 3d1b1b2737..11a373dcdb 100644 --- a/src/renderer/components/+cluster-settings/cluster-settings.route.ts +++ b/src/renderer/components/+cluster-settings/cluster-settings.route.ts @@ -7,6 +7,6 @@ export interface IClusterSettingsRouteParams extends IClusterViewRouteParams { export const clusterSettingsRoute: RouteProps = { path: `/cluster/:clusterId/settings`, -} +}; -export const clusterSettingsURL = buildURL(clusterSettingsRoute.path) +export const clusterSettingsURL = buildURL(clusterSettingsRoute.path); diff --git a/src/renderer/components/+cluster-settings/cluster-settings.tsx b/src/renderer/components/+cluster-settings/cluster-settings.tsx index 55f4bb5ec4..6188e8867e 100644 --- a/src/renderer/components/+cluster-settings/cluster-settings.tsx +++ b/src/renderer/components/+cluster-settings/cluster-settings.tsx @@ -14,7 +14,7 @@ import { IClusterSettingsRouteParams } from "./cluster-settings.route"; import { clusterStore } from "../../../common/cluster-store"; import { PageLayout } from "../layout/page-layout"; import { requestMain } from "../../../common/ipc"; -import { clusterActivateHandler, clusterRefreshHandler } from "../../../common/cluster-ipc" +import { clusterActivateHandler, clusterRefreshHandler } from "../../../common/cluster-ipc"; interface Props extends RouteComponentProps { } @@ -22,7 +22,7 @@ interface Props extends RouteComponentProps { @observer export class ClusterSettings extends React.Component { get clusterId() { - return this.props.match.params.clusterId + return this.props.match.params.clusterId; } get cluster(): Cluster { @@ -37,18 +37,18 @@ export class ClusterSettings extends React.Component { reaction(() => this.clusterId, clusterId => clusterStore.setActive(clusterId), { fireImmediately: true, }) - ]) + ]); } refreshCluster = async () => { if (this.cluster) { - await requestMain(clusterActivateHandler, this.cluster.id) - await requestMain(clusterRefreshHandler, this.cluster.id) + await requestMain(clusterActivateHandler, this.cluster.id); + await requestMain(clusterRefreshHandler, this.cluster.id); } - } + }; render() { - const cluster = this.cluster + const cluster = this.cluster; if (!cluster) return null; const header = ( <> diff --git a/src/renderer/components/+cluster-settings/components/cluster-home-dir-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-home-dir-setting.tsx index 965333d4db..35c18cc5e5 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-home-dir-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-home-dir-setting.tsx @@ -27,7 +27,7 @@ export class ClusterHomeDirSetting extends React.Component { onChange = (value: string) => { this.directory = value; - } + }; render() { return ( diff --git a/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx index fb35778f6c..6f893a48fb 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx @@ -35,14 +35,14 @@ export class ClusterIconSetting extends React.Component { cluster.preferences.icon = undefined; } } catch (e) { - this.errorText = e.toString() - this.status = GeneralInputStatus.ERROR + this.errorText = e.toString(); + this.status = GeneralInputStatus.ERROR; } } getClearButton() { if (this.props.cluster.preferences.icon) { - return + return ; } } diff --git a/src/renderer/components/+cluster-settings/components/cluster-name-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-name-setting.tsx index 54d76c08eb..631c6d54ef 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-name-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-name-setting.tsx @@ -28,7 +28,7 @@ export class ClusterNameSetting extends React.Component { onChange = (value: string) => { this.name = value; - } + }; render() { return ( diff --git a/src/renderer/components/+cluster-settings/components/cluster-prometheus-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-prometheus-setting.tsx index ff1f6fd62d..d3bc9b4e46 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-prometheus-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-prometheus-setting.tsx @@ -59,14 +59,14 @@ export class ClusterPrometheusSetting extends React.Component { service: parsed[1], port: parseInt(parsed[2]), prefix: apiPrefix - } - } + }; + }; onSaveProvider = () => { this.props.cluster.preferences.prometheusProvider = this.provider ? { type: this.provider } : null; - } + }; onSavePath = () => { this.props.cluster.preferences.prometheus = this.parsePrometheusPath(); diff --git a/src/renderer/components/+cluster-settings/components/cluster-proxy-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-proxy-setting.tsx index 8409cc5bde..d43f571495 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-proxy-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-proxy-setting.tsx @@ -28,7 +28,7 @@ export class ClusterProxySetting extends React.Component { onChange = (value: string) => { this.proxy = value; - } + }; render() { return ( diff --git a/src/renderer/components/+cluster-settings/components/install-feature.tsx b/src/renderer/components/+cluster-settings/components/install-feature.tsx index adfc8f2b5f..729dd2b1cd 100644 --- a/src/renderer/components/+cluster-settings/components/install-feature.tsx +++ b/src/renderer/components/+cluster-settings/components/install-feature.tsx @@ -19,21 +19,21 @@ export class InstallFeature extends React.Component { @observable message = ""; componentDidMount() { - const feature = this.props.feature - const cluster = this.props.cluster + const feature = this.props.feature; + const cluster = this.props.cluster; const statusUpdate = interval(20, () => { - feature.updateStatus(cluster) - }) - statusUpdate.start(true) + feature.updateStatus(cluster); + }); + statusUpdate.start(true); disposeOnUnmount(this, () => { - statusUpdate.stop() - }) + statusUpdate.stop(); + }); disposeOnUnmount(this, reaction(() => feature.status.installed, () => { this.loading = false; - this.message = "" + this.message = ""; }, { equals: comparer.structural }) ); } @@ -60,8 +60,8 @@ export class InstallFeature extends React.Component { accent disabled={disabled} onClick={this.runAction(async () => { - this.message = "Uninstalling feature ..." - feature.uninstall(cluster) + this.message = "Uninstalling feature ..."; + feature.uninstall(cluster); })} > Uninstall @@ -72,8 +72,8 @@ export class InstallFeature extends React.Component { primary disabled={disabled} onClick={this.runAction(async () =>{ - this.message = "Installing feature ..." - feature.install(cluster) + this.message = "Installing feature ..."; + feature.install(cluster); })} > Install diff --git a/src/renderer/components/+cluster-settings/components/remove-cluster-button.tsx b/src/renderer/components/+cluster-settings/components/remove-cluster-button.tsx index f407ee383a..5ae8d068f2 100644 --- a/src/renderer/components/+cluster-settings/components/remove-cluster-button.tsx +++ b/src/renderer/components/+cluster-settings/components/remove-cluster-button.tsx @@ -23,7 +23,7 @@ export class RemoveClusterButton extends React.Component { ok: async () => { await clusterStore.removeById(cluster.id); } - }) + }); } render() { diff --git a/src/renderer/components/+cluster-settings/features.tsx b/src/renderer/components/+cluster-settings/features.tsx index 74e6a28f13..271a6e69b1 100644 --- a/src/renderer/components/+cluster-settings/features.tsx +++ b/src/renderer/components/+cluster-settings/features.tsx @@ -22,7 +22,7 @@ export class Features extends React.Component {

- ) + ); })} ); diff --git a/src/renderer/components/+cluster-settings/index.ts b/src/renderer/components/+cluster-settings/index.ts index 75dd6e60ea..edab795e29 100644 --- a/src/renderer/components/+cluster-settings/index.ts +++ b/src/renderer/components/+cluster-settings/index.ts @@ -1,2 +1,2 @@ -export * from "./cluster-settings.route" -export * from "./cluster-settings" +export * from "./cluster-settings.route"; +export * from "./cluster-settings"; diff --git a/src/renderer/components/+cluster-settings/status.tsx b/src/renderer/components/+cluster-settings/status.tsx index 79fb62c860..319b42e104 100644 --- a/src/renderer/components/+cluster-settings/status.tsx +++ b/src/renderer/components/+cluster-settings/status.tsx @@ -14,7 +14,7 @@ export class Status extends React.Component { @autobind() openKubeconfig() { const { cluster } = this.props; - shell.showItemInFolder(cluster.kubeConfigPath) + shell.showItemInFolder(cluster.kubeConfigPath); } renderStatusRows() { diff --git a/src/renderer/components/+cluster/cluster-issues.tsx b/src/renderer/components/+cluster/cluster-issues.tsx index eea222b5c4..a2959cda20 100644 --- a/src/renderer/components/+cluster/cluster-issues.tsx +++ b/src/renderer/components/+cluster/cluster-issues.tsx @@ -1,4 +1,4 @@ -import "./cluster-issues.scss" +import "./cluster-issues.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -43,7 +43,7 @@ export class ClusterIssues extends React.Component { // Node bad conditions nodesStore.items.forEach(node => { - const { kind, selfLink, getId, getName } = node + const { kind, selfLink, getId, getName } = node; node.getWarningConditions().forEach(({ message }) => { warnings.push({ kind, @@ -51,8 +51,8 @@ export class ClusterIssues extends React.Component { getName, selfLink, message, - }) - }) + }); + }); }); // Warning events for Workloads @@ -67,7 +67,7 @@ export class ClusterIssues extends React.Component { kind, selfLink: lookupApiLink(involvedObject, error), }); - }) + }); return warnings; } diff --git a/src/renderer/components/+cluster/cluster-metrics.tsx b/src/renderer/components/+cluster/cluster-metrics.tsx index 077adde70a..12973b1514 100644 --- a/src/renderer/components/+cluster/cluster-metrics.tsx +++ b/src/renderer/components/+cluster/cluster-metrics.tsx @@ -72,7 +72,7 @@ export const ClusterMetrics = observer(() => { return ; } if (!memoryCapacity || !cpuCapacity) { - return + return ; } return ( {

Specified limits are higher than node capacity!

); - } + }; const renderCharts = () => { const data = getMetricLastPoints(clusterStore.metrics); @@ -168,7 +168,7 @@ export const ClusterPieCharts = observer(() => { ); - } + }; const renderContent = () => { const { masterNodes, workerNodes } = nodesStore; @@ -194,11 +194,11 @@ export const ClusterPieCharts = observer(() => { return ; } return renderCharts(); - } + }; return (
{renderContent()}
); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/renderer/components/+cluster/cluster.route.ts b/src/renderer/components/+cluster/cluster.route.ts index fbe1c47b86..f9cf7a390c 100644 --- a/src/renderer/components/+cluster/cluster.route.ts +++ b/src/renderer/components/+cluster/cluster.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const clusterRoute: RouteProps = { path: "/cluster" -} +}; -export const clusterURL = buildURL(clusterRoute.path) +export const clusterURL = buildURL(clusterRoute.path); diff --git a/src/renderer/components/+cluster/cluster.store.ts b/src/renderer/components/+cluster/cluster.store.ts index 3af42297b0..63d8f07b3b 100644 --- a/src/renderer/components/+cluster/cluster.store.ts +++ b/src/renderer/components/+cluster/cluster.store.ts @@ -18,7 +18,7 @@ export enum MetricNodeRole { @autobind() export class ClusterStore extends KubeObjectStore { - api = clusterApi + api = clusterApi; @observable metrics: Partial = {}; @observable liveMetrics: Partial = {}; @@ -35,7 +35,7 @@ export class ClusterStore extends KubeObjectStore { Object.assign(this, storage.get()); reaction(() => { const { metricType, metricNodeRole } = this; - return { metricType, metricNodeRole } + return { metricType, metricNodeRole }; }, settings => storage.set(settings) ); @@ -85,9 +85,9 @@ export class ClusterStore extends KubeObjectStore { getMetricsValues(source: Partial): [number, string][] { switch (this.metricType) { case MetricType.CPU: - return normalizeMetrics(source.cpuUsage).data.result[0].values + return normalizeMetrics(source.cpuUsage).data.result[0].values; case MetricType.MEMORY: - return normalizeMetrics(source.memoryUsage).data.result[0].values + return normalizeMetrics(source.memoryUsage).data.result[0].values; default: return []; } diff --git a/src/renderer/components/+cluster/cluster.tsx b/src/renderer/components/+cluster/cluster.tsx index 9a1ce47123..588c483295 100644 --- a/src/renderer/components/+cluster/cluster.tsx +++ b/src/renderer/components/+cluster/cluster.tsx @@ -1,4 +1,4 @@ -import "./cluster.scss" +import "./cluster.scss"; import React from "react"; import { computed, reaction } from "mobx"; @@ -21,19 +21,19 @@ export class Cluster extends React.Component { private dependentStores = [nodesStore, podsStore]; private watchers = [ - interval(60, () => { getHostedCluster().available && clusterStore.getMetrics()}), - interval(20, () => { getHostedCluster().available && eventStore.loadAll()}) + interval(60, () => { getHostedCluster().available && clusterStore.getMetrics();}), + interval(20, () => { getHostedCluster().available && eventStore.loadAll();}) ]; @computed get isLoaded() { - return nodesStore.isLoaded && podsStore.isLoaded + return nodesStore.isLoaded && podsStore.isLoaded; } // todo: refactor async componentDidMount() { const { dependentStores } = this; if (!isAllowedResource("nodes")) { - dependentStores.splice(dependentStores.indexOf(nodesStore), 1) + dependentStores.splice(dependentStores.indexOf(nodesStore), 1); } this.watchers.forEach(watcher => watcher.start(true)); @@ -49,7 +49,7 @@ export class Cluster extends React.Component { () => clusterStore.metricNodeRole, () => this.watchers.forEach(watcher => watcher.restart()) ) - ]) + ]); } render() { @@ -67,6 +67,6 @@ export class Cluster extends React.Component { )}
- ) + ); } } diff --git a/src/renderer/components/+cluster/index.ts b/src/renderer/components/+cluster/index.ts index 62a1be24fb..d9be64692d 100644 --- a/src/renderer/components/+cluster/index.ts +++ b/src/renderer/components/+cluster/index.ts @@ -1,2 +1,2 @@ -export * from "./cluster.route" +export * from "./cluster.route"; diff --git a/src/renderer/components/+config-autoscalers/hpa-details.tsx b/src/renderer/components/+config-autoscalers/hpa-details.tsx index a3461f629d..b068c28361 100644 --- a/src/renderer/components/+config-autoscalers/hpa-details.tsx +++ b/src/renderer/components/+config-autoscalers/hpa-details.tsx @@ -51,7 +51,7 @@ export class HpaDetails extends React.Component { ); } - } + }; return ( @@ -68,7 +68,7 @@ export class HpaDetails extends React.Component { {name} {values} - ) + ); }) }
@@ -113,7 +113,7 @@ export class HpaDetails extends React.Component { tooltip={tooltip} className={cssNames({ [type.toLowerCase()]: isReady })} /> - ) + ); })} @@ -132,7 +132,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "HorizontalPodAutoscaler", @@ -141,4 +141,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+config-autoscalers/hpa.route.ts b/src/renderer/components/+config-autoscalers/hpa.route.ts index 0828db146b..404bab8f88 100644 --- a/src/renderer/components/+config-autoscalers/hpa.route.ts +++ b/src/renderer/components/+config-autoscalers/hpa.route.ts @@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const hpaRoute: RouteProps = { path: "/hpa" -} +}; export interface IHpaRouteParams { } -export const hpaURL = buildURL(hpaRoute.path) +export const hpaURL = buildURL(hpaRoute.path); diff --git a/src/renderer/components/+config-autoscalers/hpa.store.ts b/src/renderer/components/+config-autoscalers/hpa.store.ts index 240f42a309..478c2ca563 100644 --- a/src/renderer/components/+config-autoscalers/hpa.store.ts +++ b/src/renderer/components/+config-autoscalers/hpa.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class HPAStore extends KubeObjectStore { - api = hpaApi + api = hpaApi; } export const hpaStore = new HPAStore(); diff --git a/src/renderer/components/+config-autoscalers/hpa.tsx b/src/renderer/components/+config-autoscalers/hpa.tsx index 01e18da2f5..f955ce098d 100644 --- a/src/renderer/components/+config-autoscalers/hpa.tsx +++ b/src/renderer/components/+config-autoscalers/hpa.tsx @@ -1,4 +1,4 @@ -import "./hpa.scss" +import "./hpa.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -78,7 +78,7 @@ export class HorizontalPodAutoscalers extends React.Component { tooltip={tooltip} className={cssNames(type.toLowerCase())} /> - ) + ); }) ]} /> diff --git a/src/renderer/components/+config-autoscalers/index.ts b/src/renderer/components/+config-autoscalers/index.ts index 4d3cedf89c..99d994add1 100644 --- a/src/renderer/components/+config-autoscalers/index.ts +++ b/src/renderer/components/+config-autoscalers/index.ts @@ -1,3 +1,3 @@ -export * from "./hpa" -export * from "./hpa-details" -export * from "./hpa.route" +export * from "./hpa"; +export * from "./hpa-details"; +export * from "./hpa.route"; diff --git a/src/renderer/components/+config-maps/config-map-details.tsx b/src/renderer/components/+config-maps/config-map-details.tsx index 0a890f6d04..bd796a2323 100644 --- a/src/renderer/components/+config-maps/config-map-details.tsx +++ b/src/renderer/components/+config-maps/config-map-details.tsx @@ -31,7 +31,7 @@ export class ConfigMapDetails extends React.Component { this.data.replace(configMap.data); // refresh } }) - ]) + ]); } save = async () => { @@ -47,7 +47,7 @@ export class ConfigMapDetails extends React.Component { } finally { this.isSaving = false; } - } + }; render() { const { object: configMap } = this.props; @@ -75,7 +75,7 @@ export class ConfigMapDetails extends React.Component { /> - ) + ); }) } )} - ) - }) + ); + }); } render() { diff --git a/src/renderer/components/+extensions/index.ts b/src/renderer/components/+extensions/index.ts index 8946a5f6fe..ff9343e704 100644 --- a/src/renderer/components/+extensions/index.ts +++ b/src/renderer/components/+extensions/index.ts @@ -1,2 +1,2 @@ -export * from "./extensions.route" -export * from "./extensions" +export * from "./extensions.route"; +export * from "./extensions"; diff --git a/src/renderer/components/+landing-page/index.tsx b/src/renderer/components/+landing-page/index.tsx index 36f2dce350..4bdb2a706c 100644 --- a/src/renderer/components/+landing-page/index.tsx +++ b/src/renderer/components/+landing-page/index.tsx @@ -1,2 +1,2 @@ -export * from "./landing-page.route" -export * from "./landing-page" \ No newline at end of file +export * from "./landing-page.route"; +export * from "./landing-page"; \ No newline at end of file diff --git a/src/renderer/components/+landing-page/landing-page.route.ts b/src/renderer/components/+landing-page/landing-page.route.ts index 344cc48033..5fa9f2321e 100644 --- a/src/renderer/components/+landing-page/landing-page.route.ts +++ b/src/renderer/components/+landing-page/landing-page.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const landingRoute: RouteProps = { path: "/landing" -} +}; -export const landingURL = buildURL(landingRoute.path) +export const landingURL = buildURL(landingRoute.path); diff --git a/src/renderer/components/+landing-page/landing-page.tsx b/src/renderer/components/+landing-page/landing-page.tsx index 68d71701c5..5c1e34297c 100644 --- a/src/renderer/components/+landing-page/landing-page.tsx +++ b/src/renderer/components/+landing-page/landing-page.tsx @@ -1,4 +1,4 @@ -import "./landing-page.scss" +import "./landing-page.scss"; import React from "react"; import { observable } from "mobx"; import { observer } from "mobx-react"; @@ -37,6 +37,6 @@ export class LandingPage extends React.Component { )} - ) + ); } } diff --git a/src/renderer/components/+namespaces/add-namespace-dialog.tsx b/src/renderer/components/+namespaces/add-namespace-dialog.tsx index 8c09c80138..a31a44de94 100644 --- a/src/renderer/components/+namespaces/add-namespace-dialog.tsx +++ b/src/renderer/components/+namespaces/add-namespace-dialog.tsx @@ -1,4 +1,4 @@ -import "./add-namespace-dialog.scss" +import "./add-namespace-dialog.scss"; import React from "react"; import { observable } from "mobx"; @@ -33,7 +33,7 @@ export class AddNamespaceDialog extends React.Component { close = () => { AddNamespaceDialog.close(); - } + }; addNamespace = async () => { const { namespace } = this; @@ -45,7 +45,7 @@ export class AddNamespaceDialog extends React.Component { Notifications.error(err); onError && onError(err); } - } + }; render() { const { ...dialogProps } = this.props; @@ -74,6 +74,6 @@ export class AddNamespaceDialog extends React.Component { - ) + ); } } diff --git a/src/renderer/components/+namespaces/index.ts b/src/renderer/components/+namespaces/index.ts index d0b9647dc7..3a03949618 100644 --- a/src/renderer/components/+namespaces/index.ts +++ b/src/renderer/components/+namespaces/index.ts @@ -1,4 +1,4 @@ -export * from "./namespaces.route" -export * from "./namespaces" -export * from "./namespace-details" -export * from "./add-namespace-dialog" +export * from "./namespaces.route"; +export * from "./namespaces"; +export * from "./namespace-details"; +export * from "./add-namespace-dialog"; diff --git a/src/renderer/components/+namespaces/namespace-details.tsx b/src/renderer/components/+namespaces/namespace-details.tsx index a7e2abf2f3..7599562333 100644 --- a/src/renderer/components/+namespaces/namespace-details.tsx +++ b/src/renderer/components/+namespaces/namespace-details.tsx @@ -62,4 +62,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+namespaces/namespace-select.tsx b/src/renderer/components/+namespaces/namespace-select.tsx index 7657a25345..e1c64f8342 100644 --- a/src/renderer/components/+namespaces/namespace-select.tsx +++ b/src/renderer/components/+namespaces/namespace-select.tsx @@ -1,4 +1,4 @@ -import "./namespace-select.scss" +import "./namespace-select.scss"; import React from "react"; import { computed } from "mobx"; @@ -62,7 +62,7 @@ export class NamespaceSelect extends React.Component { {value} ); - } + }; render() { const { className, showIcons, showClusterOption, clusterOptionLabel, customizeOptions, ...selectProps } = this.props; @@ -83,8 +83,8 @@ export class NamespaceSelectFilter extends React.Component { render() { const { contextNs, hasContext, toggleContext } = namespaceStore; let placeholder = All namespaces; - if (contextNs.length == 1) placeholder = Namespace: {contextNs[0]} - if (contextNs.length >= 2) placeholder = Namespaces: {contextNs.join(", ")} + if (contextNs.length == 1) placeholder = Namespace: {contextNs[0]}; + if (contextNs.length >= 2) placeholder = Namespaces: {contextNs.join(", ")}; return ( {namespace} {isSelected && } - ) + ); }} /> - ) + ); } } diff --git a/src/renderer/components/+namespaces/namespace.store.ts b/src/renderer/components/+namespaces/namespace.store.ts index 8874aa9233..dabde6b47d 100644 --- a/src/renderer/components/+namespaces/namespace.store.ts +++ b/src/renderer/components/+namespaces/namespace.store.ts @@ -36,20 +36,20 @@ export class NamespaceStore extends KubeObjectStore { getContextParams(): Partial { return { namespaces: this.contextNs - } + }; } protected updateUrl(namespaces: string[]) { - setQueryParams({ namespaces }, { replace: true }) + setQueryParams({ namespaces }, { replace: true }); } protected async loadItems(namespaces?: string[]) { if (!isAllowedResource("namespaces")) { if (namespaces) return namespaces.map(this.getDummyNamespace); - return [] + return []; } if (namespaces) { - return Promise.all(namespaces.map(name => this.api.get({ name }))) + return Promise.all(namespaces.map(name => this.api.get({ name }))); } else { return super.loadItems(); } @@ -65,7 +65,7 @@ export class NamespaceStore extends KubeObjectStore { resourceVersion: "", selfLink: `/api/v1/namespaces/${name}` } - }) + }); } setContext(namespaces: string[]) { diff --git a/src/renderer/components/+namespaces/namespaces.route.ts b/src/renderer/components/+namespaces/namespaces.route.ts index 9d901b6ada..38c2d575d9 100644 --- a/src/renderer/components/+namespaces/namespaces.route.ts +++ b/src/renderer/components/+namespaces/namespaces.route.ts @@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const namespacesRoute: RouteProps = { path: "/namespaces" -} +}; export interface INamespacesRouteParams { } -export const namespacesURL = buildURL(namespacesRoute.path) +export const namespacesURL = buildURL(namespacesRoute.path); diff --git a/src/renderer/components/+namespaces/namespaces.tsx b/src/renderer/components/+namespaces/namespaces.tsx index 05ef3da964..f4bb96aa14 100644 --- a/src/renderer/components/+namespaces/namespaces.tsx +++ b/src/renderer/components/+namespaces/namespaces.tsx @@ -1,4 +1,4 @@ -import "./namespaces.scss" +import "./namespaces.scss"; import React from "react"; import { Trans } from "@lingui/macro"; @@ -64,6 +64,6 @@ export class Namespaces extends React.Component { /> - ) + ); } } diff --git a/src/renderer/components/+network-endpoints/endpoint-details.tsx b/src/renderer/components/+network-endpoints/endpoint-details.tsx index fa5ca675a3..df01cf612e 100644 --- a/src/renderer/components/+network-endpoints/endpoint-details.tsx +++ b/src/renderer/components/+network-endpoints/endpoint-details.tsx @@ -1,4 +1,4 @@ -import "./endpoint-details.scss" +import "./endpoint-details.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -28,7 +28,7 @@ export class EndpointDetails extends React.Component { endpoint.getEndpointSubsets().map((subset) => { return( - ) + ); }) } @@ -42,7 +42,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Endpoints", apiVersions: ["v1"], @@ -50,4 +50,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx b/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx index 399c6ca5f1..0c3c5c0436 100644 --- a/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx +++ b/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx @@ -1,4 +1,4 @@ -import "./endpoint-subset-list.scss" +import "./endpoint-subset-list.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -23,14 +23,14 @@ export class EndpointSubsetList extends React.Component { getAddressTableRow(ip: string) { const { subset } = this.props; const address = subset.getAddresses().find(address => address.getId() == ip); - return this.renderAddressTableRow(address) + return this.renderAddressTableRow(address); } @autobind() getNotReadyAddressTableRow(ip: string) { const { subset} = this.props; const address = subset.getNotReadyAddresses().find(address => address.getId() == ip); - return this.renderAddressTableRow(address) + return this.renderAddressTableRow(address); } @autobind() @@ -56,7 +56,7 @@ export class EndpointSubsetList extends React.Component { } - ) + ); } @autobind() diff --git a/src/renderer/components/+network-endpoints/endpoints.route.ts b/src/renderer/components/+network-endpoints/endpoints.route.ts index 98ecb67bdb..f350b7868e 100644 --- a/src/renderer/components/+network-endpoints/endpoints.route.ts +++ b/src/renderer/components/+network-endpoints/endpoints.route.ts @@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const endpointRoute: RouteProps = { path: "/endpoints" -} +}; export interface EndpointRouteParams { } -export const endpointURL = buildURL(endpointRoute.path) +export const endpointURL = buildURL(endpointRoute.path); diff --git a/src/renderer/components/+network-endpoints/endpoints.store.ts b/src/renderer/components/+network-endpoints/endpoints.store.ts index 5d4a6b6ff7..d61a12126e 100644 --- a/src/renderer/components/+network-endpoints/endpoints.store.ts +++ b/src/renderer/components/+network-endpoints/endpoints.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class EndpointStore extends KubeObjectStore { - api = endpointApi + api = endpointApi; } export const endpointStore = new EndpointStore(); diff --git a/src/renderer/components/+network-endpoints/endpoints.tsx b/src/renderer/components/+network-endpoints/endpoints.tsx index b32b19946c..b8862841cb 100644 --- a/src/renderer/components/+network-endpoints/endpoints.tsx +++ b/src/renderer/components/+network-endpoints/endpoints.tsx @@ -1,10 +1,10 @@ -import "./endpoints.scss" +import "./endpoints.scss"; -import React from "react" +import React from "react"; import { observer } from "mobx-react"; -import { RouteComponentProps } from "react-router-dom" -import { EndpointRouteParams } from "./endpoints.route" -import { Endpoint } from "../../api/endpoints/endpoint.api" +import { RouteComponentProps } from "react-router-dom"; +import { EndpointRouteParams } from "./endpoints.route"; +import { Endpoint } from "../../api/endpoints/endpoint.api"; import { endpointStore } from "./endpoints.store"; import { KubeObjectListLayout } from "../kube-object"; import { Trans } from "@lingui/macro"; @@ -55,6 +55,6 @@ export class Endpoints extends React.Component { } }} /> - ) + ); } } diff --git a/src/renderer/components/+network-endpoints/index.ts b/src/renderer/components/+network-endpoints/index.ts index 9a9da148d6..eb91009613 100644 --- a/src/renderer/components/+network-endpoints/index.ts +++ b/src/renderer/components/+network-endpoints/index.ts @@ -1,3 +1,3 @@ -export * from "./endpoints.route" -export * from "./endpoints" -export * from "./endpoint-details" +export * from "./endpoints.route"; +export * from "./endpoints"; +export * from "./endpoint-details"; diff --git a/src/renderer/components/+network-ingresses/index.ts b/src/renderer/components/+network-ingresses/index.ts index 46769f9275..3977538fc7 100644 --- a/src/renderer/components/+network-ingresses/index.ts +++ b/src/renderer/components/+network-ingresses/index.ts @@ -1,3 +1,3 @@ -export * from "./ingresses.route" -export * from "./ingresses" -export * from "./ingress-details" +export * from "./ingresses.route"; +export * from "./ingresses"; +export * from "./ingress-details"; diff --git a/src/renderer/components/+network-ingresses/ingress-charts.tsx b/src/renderer/components/+network-ingresses/ingress-charts.tsx index 89ceb86b3d..7ea16a92a3 100644 --- a/src/renderer/components/+network-ingresses/ingress-charts.tsx +++ b/src/renderer/components/+network-ingresses/ingress-charts.tsx @@ -94,4 +94,4 @@ export const IngressCharts = observer(() => { data={{ datasets: datasets[tabId] }} /> ); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/renderer/components/+network-ingresses/ingress-details.tsx b/src/renderer/components/+network-ingresses/ingress-details.tsx index 5a4479672b..a258294abe 100644 --- a/src/renderer/components/+network-ingresses/ingress-details.tsx +++ b/src/renderer/components/+network-ingresses/ingress-details.tsx @@ -30,8 +30,8 @@ export class IngressDetails extends React.Component { } renderPaths(ingress: Ingress) { - const { spec: { rules } } = ingress - if (!rules || !rules.length) return null + const { spec: { rules } } = ingress; + if (!rules || !rules.length) return null; return rules.map((rule, index) => { return (
@@ -48,7 +48,7 @@ export class IngressDetails extends React.Component { { rule.http.paths.map((path, index) => { - const backend = `${path.backend.serviceName}:${path.backend.servicePort}` + const backend = `${path.backend.serviceName}:${path.backend.servicePort}`; return ( {path.path || ""} @@ -56,18 +56,18 @@ export class IngressDetails extends React.Component {

{backend}

- ) + ); }) } )}
- ) - }) + ); + }); } renderIngressPoints(ingressPoints: ILoadBalancerIngress[]) { - if (!ingressPoints || ingressPoints.length === 0) return null + if (!ingressPoints || ingressPoints.length === 0) return null; return (
@@ -81,11 +81,11 @@ export class IngressDetails extends React.Component { {hostname ? hostname : "-"} {ip ? ip : "-"} - )}) + );}) })
- ) + ); } render() { @@ -94,7 +94,7 @@ export class IngressDetails extends React.Component { return null; } const { spec, status } = ingress; - const ingressPoints = status?.loadBalancer?.ingress + const ingressPoints = status?.loadBalancer?.ingress; const { metrics } = ingressStore; const metricTabs = [ Network, @@ -128,7 +128,7 @@ export class IngressDetails extends React.Component { Load-Balancer Ingress Points}/> {this.renderIngressPoints(ingressPoints)} - ) + ); } } @@ -138,7 +138,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Ingress", apiVersions: ["extensions/v1beta1"], @@ -146,4 +146,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+network-ingresses/ingresses.route.ts b/src/renderer/components/+network-ingresses/ingresses.route.ts index 1c1f2941f4..827707bcef 100644 --- a/src/renderer/components/+network-ingresses/ingresses.route.ts +++ b/src/renderer/components/+network-ingresses/ingresses.route.ts @@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const ingressRoute: RouteProps = { path: "/ingresses" -} +}; export interface IngressRouteParams { } -export const ingressURL = buildURL(ingressRoute.path) +export const ingressURL = buildURL(ingressRoute.path); diff --git a/src/renderer/components/+network-ingresses/ingresses.tsx b/src/renderer/components/+network-ingresses/ingresses.tsx index 2ecfeb1585..bba5615915 100644 --- a/src/renderer/components/+network-ingresses/ingresses.tsx +++ b/src/renderer/components/+network-ingresses/ingresses.tsx @@ -1,10 +1,10 @@ -import "./ingresses.scss" +import "./ingresses.scss"; -import React from "react" +import React from "react"; import { observer } from "mobx-react"; -import { RouteComponentProps } from "react-router-dom" -import { IngressRouteParams } from "./ingresses.route" -import { Ingress } from "../../api/endpoints/ingress.api" +import { RouteComponentProps } from "react-router-dom"; +import { IngressRouteParams } from "./ingresses.route"; +import { Ingress } from "../../api/endpoints/ingress.api"; import { ingressStore } from "./ingress.store"; import { KubeObjectListLayout } from "../kube-object"; import { Trans } from "@lingui/macro"; @@ -58,6 +58,6 @@ export class Ingresses extends React.Component { } }} /> - ) + ); } } diff --git a/src/renderer/components/+network-policies/index.ts b/src/renderer/components/+network-policies/index.ts index 0521db2765..f0092b8bcc 100644 --- a/src/renderer/components/+network-policies/index.ts +++ b/src/renderer/components/+network-policies/index.ts @@ -1,3 +1,3 @@ -export * from "./network-policies.route" -export * from "./network-policies" -export * from "./network-policy-details" +export * from "./network-policies.route"; +export * from "./network-policies"; +export * from "./network-policy-details"; diff --git a/src/renderer/components/+network-policies/network-policies.route.ts b/src/renderer/components/+network-policies/network-policies.route.ts index ab609200ce..16b507cd55 100644 --- a/src/renderer/components/+network-policies/network-policies.route.ts +++ b/src/renderer/components/+network-policies/network-policies.route.ts @@ -3,7 +3,7 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const networkPoliciesRoute: RouteProps = { path: "/network-policies" -} +}; export interface INetworkPoliciesRouteParams { } diff --git a/src/renderer/components/+network-policies/network-policies.tsx b/src/renderer/components/+network-policies/network-policies.tsx index f28917f653..b54b6a80aa 100644 --- a/src/renderer/components/+network-policies/network-policies.tsx +++ b/src/renderer/components/+network-policies/network-policies.tsx @@ -1,4 +1,4 @@ -import "./network-policies.scss" +import "./network-policies.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -49,6 +49,6 @@ export class NetworkPolicies extends React.Component { item.getAge(), ]} /> - ) + ); } } diff --git a/src/renderer/components/+network-policies/network-policy-details.tsx b/src/renderer/components/+network-policies/network-policy-details.tsx index 6f38f6d02b..ac9f1d7ba2 100644 --- a/src/renderer/components/+network-policies/network-policy-details.tsx +++ b/src/renderer/components/+network-policies/network-policy-details.tsx @@ -1,4 +1,4 @@ -import "./network-policy-details.scss" +import "./network-policy-details.scss"; import get from "lodash/get"; import React, { Fragment } from "react"; @@ -27,10 +27,10 @@ export class NetworkPolicyDetails extends React.Component { From}/> {from.map(item => Object.keys(item).map(key => { - const data = get(item, key) + const data = get(item, key); if (key === "ipBlock") { const { cidr, except } = data as IPolicyIpBlock; - if (!cidr) return + if (!cidr) return; return ( cidr: {cidr}, {" "} @@ -38,9 +38,9 @@ export class NetworkPolicyDetails extends React.Component { `except: ${except.join(", ")}` } - ) + ); } - const selector: IPolicySelector = data + const selector: IPolicySelector = data; if (selector.matchLabels) { return ( @@ -51,7 +51,7 @@ export class NetworkPolicyDetails extends React.Component { .join(", ") } - ) + ); } else { return ((empty)); @@ -69,10 +69,10 @@ export class NetworkPolicyDetails extends React.Component { <> To}/> {to.map(item => { - const { ipBlock } = item - if (!ipBlock) return - const { cidr, except } = ipBlock - if (!cidr) return + const { ipBlock } = item; + if (!ipBlock) return; + const { cidr, except } = ipBlock; + if (!cidr) return; return ( cidr: {cidr}, {" "} @@ -80,7 +80,7 @@ export class NetworkPolicyDetails extends React.Component { `except: ${except.join(", ")}` } - ) + ); })} ); @@ -116,7 +116,7 @@ export class NetworkPolicyDetails extends React.Component { {this.renderIngressFrom(ingress)} - ) + ); })} )} @@ -133,7 +133,7 @@ export class NetworkPolicyDetails extends React.Component { {this.renderEgressTo(egress)} - ) + ); })} )} @@ -148,7 +148,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "NetworkPolicy", @@ -157,4 +157,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+network-policies/network-policy.store.ts b/src/renderer/components/+network-policies/network-policy.store.ts index 0f37de3ac0..e33a17fa09 100644 --- a/src/renderer/components/+network-policies/network-policy.store.ts +++ b/src/renderer/components/+network-policies/network-policy.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class NetworkPolicyStore extends KubeObjectStore { - api = networkPolicyApi + api = networkPolicyApi; } export const networkPolicyStore = new NetworkPolicyStore(); diff --git a/src/renderer/components/+network-services/index.ts b/src/renderer/components/+network-services/index.ts index 4f64dcf2c9..de2b4282d5 100644 --- a/src/renderer/components/+network-services/index.ts +++ b/src/renderer/components/+network-services/index.ts @@ -1,3 +1,3 @@ -export * from "./services.route" -export * from "./services" -export * from "./service-details" +export * from "./services.route"; +export * from "./services"; +export * from "./service-details"; diff --git a/src/renderer/components/+network-services/service-details-endpoint.tsx b/src/renderer/components/+network-services/service-details-endpoint.tsx index a16d1c2c0a..df0aac76ec 100644 --- a/src/renderer/components/+network-services/service-details-endpoint.tsx +++ b/src/renderer/components/+network-services/service-details-endpoint.tsx @@ -15,12 +15,12 @@ interface Props { @observer export class ServiceDetailsEndpoint extends React.Component { render() { - const { endpoint } = this.props + const { endpoint } = this.props; if (!endpoint && !endpointStore.isLoaded) return (
); if (!endpoint) { - return null + return null; } return (
@@ -44,6 +44,6 @@ export class ServiceDetailsEndpoint extends React.Component {
- ) + ); } } diff --git a/src/renderer/components/+network-services/service-details.tsx b/src/renderer/components/+network-services/service-details.tsx index e43f7fab0c..5d659cc7e1 100644 --- a/src/renderer/components/+network-services/service-details.tsx +++ b/src/renderer/components/+network-services/service-details.tsx @@ -1,4 +1,4 @@ -import "./service-details.scss" +import "./service-details.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -24,14 +24,14 @@ export class ServiceDetails extends React.Component { if (!endpointStore.isLoaded) { endpointStore.loadAll(); } - endpointApi.watch() + endpointApi.watch(); } render() { const { object: service } = this.props; if (!service) return; const { spec } = service; - const endpoint = endpointStore.getByName(service.getName(), service.getNs()) + const endpoint = endpointStore.getByName(service.getName(), service.getNs()); return (
@@ -89,7 +89,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Service", @@ -98,4 +98,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+network-services/service-port-component.tsx b/src/renderer/components/+network-services/service-port-component.tsx index 252bf8eb16..8b3dba03c4 100644 --- a/src/renderer/components/+network-services/service-port-component.tsx +++ b/src/renderer/components/+network-services/service-port-component.tsx @@ -1,15 +1,15 @@ -import "./service-port-component.scss" +import "./service-port-component.scss"; import React from "react"; import { observer } from "mobx-react"; import { t } from "@lingui/macro"; import { Service, ServicePort } from "../../api/endpoints"; import { _i18n } from "../../i18n"; -import { apiBase } from "../../api" +import { apiBase } from "../../api"; import { observable } from "mobx"; import { cssNames } from "../../utils"; import { Notifications } from "../notifications"; -import { Spinner } from "../spinner" +import { Spinner } from "../spinner"; interface Props { service: Service; @@ -24,7 +24,7 @@ export class ServicePortComponent extends React.Component { const { service, port } = this.props; this.waiting = true; try { - await apiBase.post(`/pods/${service.getNs()}/service/${service.getName()}/port-forward/${port.port}`, {}) + await apiBase.post(`/pods/${service.getNs()}/service/${service.getName()}/port-forward/${port.port}`, {}); } catch(error) { Notifications.error(error); } finally { diff --git a/src/renderer/components/+network-services/services.route.ts b/src/renderer/components/+network-services/services.route.ts index 8cc42090a7..b23087829d 100644 --- a/src/renderer/components/+network-services/services.route.ts +++ b/src/renderer/components/+network-services/services.route.ts @@ -3,7 +3,7 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const servicesRoute: RouteProps = { path: "/services" -} +}; export interface IServicesRouteParams { } diff --git a/src/renderer/components/+network-services/services.store.ts b/src/renderer/components/+network-services/services.store.ts index d3e3c7b983..8c6d16d746 100644 --- a/src/renderer/components/+network-services/services.store.ts +++ b/src/renderer/components/+network-services/services.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class ServiceStore extends KubeObjectStore { - api = serviceApi + api = serviceApi; } export const serviceStore = new ServiceStore(); diff --git a/src/renderer/components/+network-services/services.tsx b/src/renderer/components/+network-services/services.tsx index ed7951a78b..0aacbb602e 100644 --- a/src/renderer/components/+network-services/services.tsx +++ b/src/renderer/components/+network-services/services.tsx @@ -1,4 +1,4 @@ -import "./services.scss" +import "./services.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -72,6 +72,6 @@ export class Services extends React.Component { { title: service.getStatus(), className: service.getStatus().toLowerCase() }, ]} /> - ) + ); } } diff --git a/src/renderer/components/+network/index.ts b/src/renderer/components/+network/index.ts index c5282c5b0e..9a58dc59a6 100644 --- a/src/renderer/components/+network/index.ts +++ b/src/renderer/components/+network/index.ts @@ -1,2 +1,2 @@ -export * from "./network.route" -export * from "./network" +export * from "./network.route"; +export * from "./network"; diff --git a/src/renderer/components/+network/network.route.ts b/src/renderer/components/+network/network.route.ts index c13f7cedf7..de36bfc77a 100644 --- a/src/renderer/components/+network/network.route.ts +++ b/src/renderer/components/+network/network.route.ts @@ -1,12 +1,12 @@ -import { RouteProps } from "react-router" +import { RouteProps } from "react-router"; import { Network } from "./network"; import { servicesURL } from "../+network-services"; import { IURLParams } from "../../../common/utils/buildUrl"; export const networkRoute: RouteProps = { get path() { - return Network.tabRoutes.map(({ routePath }) => routePath).flat() + return Network.tabRoutes.map(({ routePath }) => routePath).flat(); } -} +}; export const networkURL = (params?: IURLParams) => servicesURL(params); diff --git a/src/renderer/components/+network/network.tsx b/src/renderer/components/+network/network.tsx index 9e0b2d92c6..2cc99eb367 100644 --- a/src/renderer/components/+network/network.tsx +++ b/src/renderer/components/+network/network.tsx @@ -1,4 +1,4 @@ -import "./network.scss" +import "./network.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -14,7 +14,7 @@ import { isAllowedResource } from "../../../common/rbac"; @observer export class Network extends React.Component { static get tabRoutes(): TabLayoutRoute[] { - const query = namespaceStore.getContextParams() + const query = namespaceStore.getContextParams(); const routes: TabLayoutRoute[] = []; if (isAllowedResource("services")) { routes.push({ @@ -22,7 +22,7 @@ export class Network extends React.Component { component: Services, url: servicesURL({ query }), routePath: servicesRoute.path.toString(), - }) + }); } if (isAllowedResource("endpoints")) { routes.push({ @@ -30,7 +30,7 @@ export class Network extends React.Component { component: Endpoints, url: endpointURL({ query }), routePath: endpointRoute.path.toString(), - }) + }); } if (isAllowedResource("ingresses")) { routes.push({ @@ -38,7 +38,7 @@ export class Network extends React.Component { component: Ingresses, url: ingressURL({ query }), routePath: ingressRoute.path.toString(), - }) + }); } if (isAllowedResource("networkpolicies")) { routes.push({ @@ -46,14 +46,14 @@ export class Network extends React.Component { component: NetworkPolicies, url: networkPoliciesURL({ query }), routePath: networkPoliciesRoute.path.toString(), - }) + }); } - return routes + return routes; } render() { return ( - ) + ); } } diff --git a/src/renderer/components/+nodes/index.ts b/src/renderer/components/+nodes/index.ts index 4a77b1c63b..515a3d85f6 100644 --- a/src/renderer/components/+nodes/index.ts +++ b/src/renderer/components/+nodes/index.ts @@ -1,3 +1,3 @@ -export * from "./nodes" -export * from "./nodes.route" -export * from "./node-details" +export * from "./nodes"; +export * from "./nodes.route"; +export * from "./node-details"; diff --git a/src/renderer/components/+nodes/node-charts.tsx b/src/renderer/components/+nodes/node-charts.tsx index 4271181fcd..9f5e6ce6f8 100644 --- a/src/renderer/components/+nodes/node-charts.tsx +++ b/src/renderer/components/+nodes/node-charts.tsx @@ -140,7 +140,7 @@ export const NodeCharts = observer(() => { } } } - } + }; const options = [cpuOptions, memoryOptions, memoryOptions, podOptions]; @@ -151,4 +151,4 @@ export const NodeCharts = observer(() => { data={{ datasets: datasets[tabId] }} /> ); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/renderer/components/+nodes/node-details.tsx b/src/renderer/components/+nodes/node-details.tsx index 1402b77be5..653fff8d2b 100644 --- a/src/renderer/components/+nodes/node-details.tsx +++ b/src/renderer/components/+nodes/node-details.tsx @@ -42,12 +42,12 @@ export class NodeDetails extends React.Component { render() { const { object: node } = this.props; if (!node) return; - const { status } = node - const { nodeInfo, addresses, capacity, allocatable } = status + const { status } = node; + const { nodeInfo, addresses, capacity, allocatable } = status; const conditions = node.getActiveConditions(); - const taints = node.getTaints() - const childPods = podsStore.getPodsByNode(node.getName()) - const metrics = nodesStore.nodeMetrics + const taints = node.getTaints(); + const childPods = podsStore.getPodsByNode(node.getName()); + const metrics = nodesStore.nodeMetrics; const metricTabs = [ CPU, Memory, @@ -120,7 +120,7 @@ export class NodeDetails extends React.Component { Conditions} className="conditions" labelsOnly> { conditions.map(condition => { - const { type } = condition + const { type } = condition; return ( { ) }} /> - ) + ); }) } @@ -150,7 +150,7 @@ export class NodeDetails extends React.Component { maxMemory={node.getMemoryCapacity()} />
- ) + ); } } @@ -160,7 +160,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Node", @@ -169,4 +169,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+nodes/nodes.route.ts b/src/renderer/components/+nodes/nodes.route.ts index cf03a8733d..972bdababe 100644 --- a/src/renderer/components/+nodes/nodes.route.ts +++ b/src/renderer/components/+nodes/nodes.route.ts @@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const nodesRoute: RouteProps = { path: "/nodes" -} +}; export interface INodesRouteParams { } -export const nodesURL = buildURL(nodesRoute.path) +export const nodesURL = buildURL(nodesRoute.path); diff --git a/src/renderer/components/+nodes/nodes.store.ts b/src/renderer/components/+nodes/nodes.store.ts index 8c04f55ad5..94fd3e4dd9 100644 --- a/src/renderer/components/+nodes/nodes.store.ts +++ b/src/renderer/components/+nodes/nodes.store.ts @@ -1,4 +1,4 @@ -import { action, computed, observable } from "mobx" +import { action, computed, observable } from "mobx"; import { clusterApi, IClusterMetrics, INodeMetrics, Node, nodesApi } from "../../api/endpoints"; import { autobind } from "../../utils"; import { KubeObjectStore } from "../../kube-object.store"; @@ -6,7 +6,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class NodesStore extends KubeObjectStore { - api = nodesApi + api = nodesApi; @observable metrics: Partial = {}; @observable nodeMetrics: Partial = null; @@ -30,11 +30,11 @@ export class NodesStore extends KubeObjectStore { } @computed get masterNodes() { - return this.items.filter(node => node.getRoleLabels().includes("master")) + return this.items.filter(node => node.getRoleLabels().includes("master")); } @computed get workerNodes() { - return this.items.filter(node => !node.getRoleLabels().includes("master")) + return this.items.filter(node => !node.getRoleLabels().includes("master")); } getLastMetricValues(node: Node, metricNames: string[]): number[] { @@ -50,7 +50,7 @@ export class NodesStore extends KubeObjectStore { result.metric.node, result.metric.instance, result.metric.kubernetes_node, - ].includes(nodeName) + ].includes(nodeName); }); return result ? parseFloat(result.values.slice(-1)[0][1]) : 0; } catch (e) { @@ -68,5 +68,5 @@ export class NodesStore extends KubeObjectStore { } } -export const nodesStore = new NodesStore() +export const nodesStore = new NodesStore(); apiManager.registerStore(nodesStore); diff --git a/src/renderer/components/+nodes/nodes.tsx b/src/renderer/components/+nodes/nodes.tsx index 9e7c295f6c..82efc4ce92 100644 --- a/src/renderer/components/+nodes/nodes.tsx +++ b/src/renderer/components/+nodes/nodes.tsx @@ -60,7 +60,7 @@ export class Nodes extends React.Component { children: _i18n._(t`CPU:`) + ` ${Math.ceil(usage * 100) / cores}\%, ` + _i18n._(t`cores:`) + ` ${cores}` }} /> - ) + ); } renderMemoryUsage(node: Node) { @@ -77,7 +77,7 @@ export class Nodes extends React.Component { children: _i18n._(t`Memory:`) + ` ${Math.ceil(usage * 100 / capacity)}%, ${bytesToUnits(usage, 3)}` }} /> - ) + ); } renderDiskUsage(node: Node): any { @@ -94,17 +94,17 @@ export class Nodes extends React.Component { children: _i18n._(t`Disk:`) + ` ${Math.ceil(usage * 100 / capacity)}%, ${bytesToUnits(usage, 3)}` }} /> - ) + ); } renderConditions(node: Node) { if (!node.status.conditions) { - return null + return null; } const conditions = node.getActiveConditions(); return conditions.map(condition => { - const { type } = condition - const tooltipId = `node-${node.getName()}-condition-${type}` + const { type } = condition; + const tooltipId = `node-${node.getName()}-condition-${type}`; return (
{type} @@ -116,8 +116,8 @@ export class Nodes extends React.Component {
)} - ) - }) + ); + }); } render() { @@ -177,10 +177,10 @@ export class Nodes extends React.Component { node.status.nodeInfo.kubeletVersion, node.getAge(), this.renderConditions(node), - ] + ]; }} /> - ) + ); } } diff --git a/src/renderer/components/+pod-security-policies/index.ts b/src/renderer/components/+pod-security-policies/index.ts index d9401de3c8..d037873b5b 100644 --- a/src/renderer/components/+pod-security-policies/index.ts +++ b/src/renderer/components/+pod-security-policies/index.ts @@ -1,3 +1,3 @@ -export * from "./pod-security-policies.route" -export * from "./pod-security-policies" -export * from "./pod-security-policy-details" \ No newline at end of file +export * from "./pod-security-policies.route"; +export * from "./pod-security-policies"; +export * from "./pod-security-policy-details"; \ No newline at end of file diff --git a/src/renderer/components/+pod-security-policies/pod-security-policies.route.ts b/src/renderer/components/+pod-security-policies/pod-security-policies.route.ts index e69f711bea..8bee44985e 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policies.route.ts +++ b/src/renderer/components/+pod-security-policies/pod-security-policies.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const podSecurityPoliciesRoute: RouteProps = { path: "/pod-security-policies" -} +}; -export const podSecurityPoliciesURL = buildURL(podSecurityPoliciesRoute.path) +export const podSecurityPoliciesURL = buildURL(podSecurityPoliciesRoute.path); diff --git a/src/renderer/components/+pod-security-policies/pod-security-policies.store.ts b/src/renderer/components/+pod-security-policies/pod-security-policies.store.ts index 2517dcc59a..53ecde3d9d 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policies.store.ts +++ b/src/renderer/components/+pod-security-policies/pod-security-policies.store.ts @@ -5,8 +5,8 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class PodSecurityPoliciesStore extends KubeObjectStore { - api = pspApi + api = pspApi; } -export const podSecurityPoliciesStore = new PodSecurityPoliciesStore() +export const podSecurityPoliciesStore = new PodSecurityPoliciesStore(); apiManager.registerStore(podSecurityPoliciesStore); diff --git a/src/renderer/components/+pod-security-policies/pod-security-policies.tsx b/src/renderer/components/+pod-security-policies/pod-security-policies.tsx index 8ad6b77101..779a3a75ff 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policies.tsx +++ b/src/renderer/components/+pod-security-policies/pod-security-policies.tsx @@ -49,9 +49,9 @@ export class PodSecurityPolicies extends React.Component { item.isPrivileged() ? Yes : No, item.getVolumes().join(", "), item.getAge(), - ] + ]; }} /> - ) + ); } } diff --git a/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx b/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx index 2c50a4b668..5e0b812346 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx +++ b/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx @@ -33,12 +33,12 @@ export class PodSecurityPolicyDetails extends React.Component { {ranges && ( Ranges (Min-Max)} labelsOnly> {ranges.map(({ min, max }, index) => { - return + return ; })} )} - ) + ); } render() { @@ -137,7 +137,7 @@ export class PodSecurityPolicyDetails extends React.Component { {hostPorts && ( Host Ports (Min-Max)} labelsOnly> {hostPorts.map(({ min, max }, index) => { - return + return ; })} )} @@ -156,7 +156,7 @@ export class PodSecurityPolicyDetails extends React.Component { {pathPrefix} {readOnly ? Yes : No} - ) + ); })} @@ -205,7 +205,7 @@ export class PodSecurityPolicyDetails extends React.Component { )} - ) + ); } } @@ -215,4 +215,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+preferences/index.tsx b/src/renderer/components/+preferences/index.tsx index b4d669a029..7b4ae710ae 100644 --- a/src/renderer/components/+preferences/index.tsx +++ b/src/renderer/components/+preferences/index.tsx @@ -1,2 +1,2 @@ -export * from "./preferences.route" -export * from "./preferences" +export * from "./preferences.route"; +export * from "./preferences"; diff --git a/src/renderer/components/+preferences/kubectl-binaries.tsx b/src/renderer/components/+preferences/kubectl-binaries.tsx index 002ddfdcc3..3b0b258ab4 100644 --- a/src/renderer/components/+preferences/kubectl-binaries.tsx +++ b/src/renderer/components/+preferences/kubectl-binaries.tsx @@ -16,12 +16,12 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre const downloadMirrorOptions: SelectOption[] = [ { value: "default", label: "Default (Google)" }, { value: "china", label: "China (Azure)" }, - ] + ]; const save = () => { preferences.downloadBinariesPath = downloadPath; preferences.kubectlBinariesPath = binariesPath; - } + }; return ( <> diff --git a/src/renderer/components/+preferences/preferences.route.ts b/src/renderer/components/+preferences/preferences.route.ts index 8fc7e70b0e..7c880bd5fc 100644 --- a/src/renderer/components/+preferences/preferences.route.ts +++ b/src/renderer/components/+preferences/preferences.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const preferencesRoute: RouteProps = { path: "/preferences" -} +}; -export const preferencesURL = buildURL(preferencesRoute.path) +export const preferencesURL = buildURL(preferencesRoute.path); diff --git a/src/renderer/components/+preferences/preferences.tsx b/src/renderer/components/+preferences/preferences.tsx index 2fc58646df..78f2896a73 100644 --- a/src/renderer/components/+preferences/preferences.tsx +++ b/src/renderer/components/+preferences/preferences.tsx @@ -1,4 +1,4 @@ -import "./preferences.scss" +import "./preferences.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -30,14 +30,14 @@ export class Preferences extends React.Component { return themeStore.themes.map(theme => ({ label: theme.name, value: theme.id, - })) + })); } @computed get helmOptions(): SelectOption[] { return this.helmRepos.map(repo => ({ label: repo.name, value: repo, - })) + })); } async componentDidMount() { @@ -65,7 +65,7 @@ export class Preferences extends React.Component { await repoManager.addRepo(repo); this.helmAddedRepos.set(repo.name, repo); } catch (err) { - Notifications.error(Adding helm branch {repo.name} has failed: {String(err)}) + Notifications.error(Adding helm branch {repo.name} has failed: {String(err)}); } } @@ -76,20 +76,20 @@ export class Preferences extends React.Component { } catch (err) { Notifications.error( Removing helm branch {repo.name} has failed: {String(err)} - ) + ); } } onRepoSelect = async ({ value: repo }: SelectOption) => { const isAdded = this.helmAddedRepos.has(repo.name); if (isAdded) { - Notifications.ok(Helm branch {repo.name} already in use) + Notifications.ok(Helm branch {repo.name} already in use); return; } this.helmLoading = true; await this.addRepo(repo); this.helmLoading = false; - } + }; formatHelmOptionLabel = ({ value: repo }: SelectOption) => { const isAdded = this.helmAddedRepos.has(repo.name); @@ -98,8 +98,8 @@ export class Preferences extends React.Component { {repo.name} {isAdded && } - ) - } + ); + }; render() { const { preferences } = userStore; @@ -152,7 +152,7 @@ export class Preferences extends React.Component { {repo.url} - ) + ); })} @@ -185,7 +185,7 @@ export class Preferences extends React.Component { - ) + ); })} diff --git a/src/renderer/components/+storage-classes/index.ts b/src/renderer/components/+storage-classes/index.ts index 923c64adc9..3a0b106256 100644 --- a/src/renderer/components/+storage-classes/index.ts +++ b/src/renderer/components/+storage-classes/index.ts @@ -1,4 +1,4 @@ -export * from "./storage-classes.route" -export * from "./storage-classes" -export * from "./storage-class-details" +export * from "./storage-classes.route"; +export * from "./storage-classes"; +export * from "./storage-class-details"; diff --git a/src/renderer/components/+storage-classes/storage-class-details.tsx b/src/renderer/components/+storage-classes/storage-class-details.tsx index 0edbc6426b..312e2d7ea3 100644 --- a/src/renderer/components/+storage-classes/storage-class-details.tsx +++ b/src/renderer/components/+storage-classes/storage-class-details.tsx @@ -66,7 +66,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "StorageClass", @@ -75,4 +75,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+storage-classes/storage-class.store.ts b/src/renderer/components/+storage-classes/storage-class.store.ts index 9ff90bc921..9e388456a5 100644 --- a/src/renderer/components/+storage-classes/storage-class.store.ts +++ b/src/renderer/components/+storage-classes/storage-class.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class StorageClassStore extends KubeObjectStore { - api = storageClassApi + api = storageClassApi; } export const storageClassStore = new StorageClassStore(); diff --git a/src/renderer/components/+storage-classes/storage-classes.route.ts b/src/renderer/components/+storage-classes/storage-classes.route.ts index 2f809ef9f3..c75d7dd0b8 100644 --- a/src/renderer/components/+storage-classes/storage-classes.route.ts +++ b/src/renderer/components/+storage-classes/storage-classes.route.ts @@ -3,10 +3,10 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const storageClassesRoute: RouteProps = { path: "/storage-classes" -} +}; export interface IStorageClassesRouteParams { } -export const storageClassesURL = buildURL(storageClassesRoute.path) +export const storageClassesURL = buildURL(storageClassesRoute.path); diff --git a/src/renderer/components/+storage-classes/storage-classes.tsx b/src/renderer/components/+storage-classes/storage-classes.tsx index f75b48d691..b4133c8918 100644 --- a/src/renderer/components/+storage-classes/storage-classes.tsx +++ b/src/renderer/components/+storage-classes/storage-classes.tsx @@ -1,4 +1,4 @@ -import "./storage-classes.scss" +import "./storage-classes.scss"; import React from "react"; import { RouteComponentProps } from "react-router-dom"; @@ -55,6 +55,6 @@ export class StorageClasses extends React.Component { storageClass.getAge(), ]} /> - ) + ); } } diff --git a/src/renderer/components/+storage-volume-claims/index.ts b/src/renderer/components/+storage-volume-claims/index.ts index 3a8d9949b2..4f9055c1d7 100644 --- a/src/renderer/components/+storage-volume-claims/index.ts +++ b/src/renderer/components/+storage-volume-claims/index.ts @@ -1,4 +1,4 @@ -export * from "./volume-claims.route" -export * from "./volume-claims" -export * from "./volume-claim-details" +export * from "./volume-claims.route"; +export * from "./volume-claims"; +export * from "./volume-claim-details"; diff --git a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx index c75251884d..5df839c979 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx @@ -1,4 +1,4 @@ -import "./volume-claim-details.scss" +import "./volume-claim-details.scss"; import React, { Fragment } from "react"; import { reaction } from "mobx"; @@ -99,7 +99,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "PersistentVolumeClaim", @@ -108,4 +108,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+storage-volume-claims/volume-claim-disk-chart.tsx b/src/renderer/components/+storage-volume-claims/volume-claim-disk-chart.tsx index 112ec5c268..3b727f36eb 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claim-disk-chart.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claim-disk-chart.tsx @@ -38,7 +38,7 @@ export const VolumeClaimDiskChart = observer(() => { borderColor: chartCapacityColor, data: capacity.map(([x, y]) => ({ x, y })) } - ] + ]; return ( { - api = pvcApi + api = pvcApi; @observable metrics: IPvcMetrics = null; @action diff --git a/src/renderer/components/+storage-volume-claims/volume-claims.route.ts b/src/renderer/components/+storage-volume-claims/volume-claims.route.ts index b579623369..0e49681bc3 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claims.route.ts +++ b/src/renderer/components/+storage-volume-claims/volume-claims.route.ts @@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const volumeClaimsRoute: RouteProps = { path: "/persistent-volume-claims" -} +}; export interface IVolumeClaimsRouteParams { } -export const volumeClaimsURL = buildURL(volumeClaimsRoute.path) +export const volumeClaimsURL = buildURL(volumeClaimsRoute.path); diff --git a/src/renderer/components/+storage-volume-claims/volume-claims.tsx b/src/renderer/components/+storage-volume-claims/volume-claims.tsx index e0e789a2e5..84e8b9dd92 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claims.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claims.tsx @@ -1,4 +1,4 @@ -import "./volume-claims.scss" +import "./volume-claims.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -81,9 +81,9 @@ export class PersistentVolumeClaims extends React.Component { )), pvc.getAge(), { title: pvc.getStatus(), className: pvc.getStatus().toLowerCase() }, - ] + ]; }} /> - ) + ); } } diff --git a/src/renderer/components/+storage-volumes/index.ts b/src/renderer/components/+storage-volumes/index.ts index 743de7af98..895ab6444a 100644 --- a/src/renderer/components/+storage-volumes/index.ts +++ b/src/renderer/components/+storage-volumes/index.ts @@ -1,3 +1,3 @@ -export * from "./volumes.route" -export * from "./volumes" -export * from "./volume-details" +export * from "./volumes.route"; +export * from "./volumes"; +export * from "./volume-details"; diff --git a/src/renderer/components/+storage-volumes/volume-details.tsx b/src/renderer/components/+storage-volumes/volume-details.tsx index 0cbb6d3ddc..93ede8d04d 100644 --- a/src/renderer/components/+storage-volumes/volume-details.tsx +++ b/src/renderer/components/+storage-volumes/volume-details.tsx @@ -1,5 +1,5 @@ -import startCase from "lodash/startCase" -import "./volume-details.scss" +import startCase from "lodash/startCase"; +import "./volume-details.scss"; import React from "react"; import { Trans } from "@lingui/macro"; @@ -107,7 +107,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "PersistentVolume", @@ -116,4 +116,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+storage-volumes/volumes.route.ts b/src/renderer/components/+storage-volumes/volumes.route.ts index 42d4824c99..596f51f23e 100644 --- a/src/renderer/components/+storage-volumes/volumes.route.ts +++ b/src/renderer/components/+storage-volumes/volumes.route.ts @@ -3,7 +3,7 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const volumesRoute: RouteProps = { path: "/persistent-volumes" -} +}; export interface IVolumesRouteParams { } diff --git a/src/renderer/components/+storage-volumes/volumes.store.ts b/src/renderer/components/+storage-volumes/volumes.store.ts index f065c562c9..ea61525735 100644 --- a/src/renderer/components/+storage-volumes/volumes.store.ts +++ b/src/renderer/components/+storage-volumes/volumes.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class PersistentVolumesStore extends KubeObjectStore { - api = persistentVolumeApi + api = persistentVolumeApi; } export const volumesStore = new PersistentVolumesStore(); diff --git a/src/renderer/components/+storage-volumes/volumes.tsx b/src/renderer/components/+storage-volumes/volumes.tsx index c3b01e0b93..d67a9a9b09 100644 --- a/src/renderer/components/+storage-volumes/volumes.tsx +++ b/src/renderer/components/+storage-volumes/volumes.tsx @@ -1,4 +1,4 @@ -import "./volumes.scss" +import "./volumes.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -71,9 +71,9 @@ export class PersistentVolumes extends React.Component { ), volume.getAge(), { title: volume.getStatus(), className: volume.getStatus().toLowerCase() } - ] + ]; }} /> - ) + ); } } diff --git a/src/renderer/components/+storage/index.ts b/src/renderer/components/+storage/index.ts index eb218e9174..58bae55b33 100644 --- a/src/renderer/components/+storage/index.ts +++ b/src/renderer/components/+storage/index.ts @@ -1,2 +1,2 @@ -export * from "./storage.route" -export * from "./storage" +export * from "./storage.route"; +export * from "./storage"; diff --git a/src/renderer/components/+storage/storage.route.ts b/src/renderer/components/+storage/storage.route.ts index 6fe3bb6a0a..6ad17a4fdf 100644 --- a/src/renderer/components/+storage/storage.route.ts +++ b/src/renderer/components/+storage/storage.route.ts @@ -1,12 +1,12 @@ -import { RouteProps } from "react-router" +import { RouteProps } from "react-router"; import { volumeClaimsURL } from "../+storage-volume-claims"; import { Storage } from "./storage"; import { IURLParams } from "../../../common/utils/buildUrl"; export const storageRoute: RouteProps = { get path() { - return Storage.tabRoutes.map(({ routePath }) => routePath).flat() + return Storage.tabRoutes.map(({ routePath }) => routePath).flat(); } -} +}; export const storageURL = (params?: IURLParams) => volumeClaimsURL(params); diff --git a/src/renderer/components/+storage/storage.tsx b/src/renderer/components/+storage/storage.tsx index e8a105944b..97bd014760 100644 --- a/src/renderer/components/+storage/storage.tsx +++ b/src/renderer/components/+storage/storage.tsx @@ -1,4 +1,4 @@ -import "./storage.scss" +import "./storage.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -14,14 +14,14 @@ import { isAllowedResource } from "../../../common/rbac"; export class Storage extends React.Component { static get tabRoutes() { const tabRoutes: TabLayoutRoute[] = []; - const query = namespaceStore.getContextParams() + const query = namespaceStore.getContextParams(); tabRoutes.push({ title: Persistent Volume Claims, component: PersistentVolumeClaims, url: volumeClaimsURL({ query }), routePath: volumeClaimsRoute.path.toString(), - }) + }); if (isAllowedResource('persistentvolumes')) { tabRoutes.push({ @@ -38,7 +38,7 @@ export class Storage extends React.Component { component: StorageClasses, url: storageClassesURL(), routePath: storageClassesRoute.path.toString(), - }) + }); } return tabRoutes; } @@ -46,6 +46,6 @@ export class Storage extends React.Component { render() { return ( - ) + ); } } diff --git a/src/renderer/components/+user-management-roles-bindings/add-role-binding-dialog.tsx b/src/renderer/components/+user-management-roles-bindings/add-role-binding-dialog.tsx index 4225d7b96f..227b2d936e 100644 --- a/src/renderer/components/+user-management-roles-bindings/add-role-binding-dialog.tsx +++ b/src/renderer/components/+user-management-roles-bindings/add-role-binding-dialog.tsx @@ -1,4 +1,4 @@ -import "./add-role-binding-dialog.scss" +import "./add-role-binding-dialog.scss"; import React from "react"; import { computed, observable } from "mobx"; @@ -67,12 +67,12 @@ export class AddRoleBindingDialog extends React.Component { @computed get selectedBindings() { return [ ...this.selectedAccounts, - ] + ]; } close = () => { AddRoleBindingDialog.close(); - } + }; async loadData() { const stores = [ @@ -96,13 +96,13 @@ export class AddRoleBindingDialog extends React.Component { this.bindContext = role.getNs() || ""; } } - } + }; reset = () => { this.selectedRoleId = ""; this.bindContext = ""; this.selectedAccounts.clear(); - } + }; onBindContextChange = (namespace: string) => { this.bindContext = namespace; @@ -110,7 +110,7 @@ export class AddRoleBindingDialog extends React.Component { if (this.bindContext && this.bindContext !== roleContext) { this.selectedRoleId = ""; // reset previously selected role for specific context } - } + }; createBindings = async () => { const { selectedRole, bindContext: namespace, selectedBindings, bindingName, useRoleForBindingName } = this; @@ -121,7 +121,7 @@ export class AddRoleBindingDialog extends React.Component { name: item.getName(), kind: item.kind, namespace: item.getNs(), - } + }; } return item; }); @@ -152,7 +152,7 @@ export class AddRoleBindingDialog extends React.Component { }; @computed get roleOptions(): BindingSelectOption[] { - let roles = rolesStore.items as Role[] + let roles = rolesStore.items as Role[]; if (this.bindContext) { // show only cluster-roles or roles for selected context namespace roles = roles.filter(role => !role.getNs() || role.getNs() === this.bindContext); @@ -163,8 +163,8 @@ export class AddRoleBindingDialog extends React.Component { return { value: role.getId(), label: name + (namespace ? ` (${namespace})` : "") - } - }) + }; + }); } @computed get serviceAccountOptions(): BindingSelectOption[] { @@ -175,8 +175,8 @@ export class AddRoleBindingDialog extends React.Component { item: account, value: name, label: <> {name} ({namespace}) - } - }) + }; + }); } renderContents() { @@ -240,7 +240,7 @@ export class AddRoleBindingDialog extends React.Component { maxMenuHeight={200} /> - ) + ); } render() { @@ -275,6 +275,6 @@ export class AddRoleBindingDialog extends React.Component { - ) + ); } } diff --git a/src/renderer/components/+user-management-roles-bindings/index.ts b/src/renderer/components/+user-management-roles-bindings/index.ts index ca90adf052..cb69a92323 100644 --- a/src/renderer/components/+user-management-roles-bindings/index.ts +++ b/src/renderer/components/+user-management-roles-bindings/index.ts @@ -1,3 +1,3 @@ -export * from "./role-bindings" -export * from "./role-binding-details" -export * from "./add-role-binding-dialog" +export * from "./role-bindings"; +export * from "./role-binding-details"; +export * from "./add-role-binding-dialog"; diff --git a/src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx b/src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx index afa1d1e43c..178aada344 100644 --- a/src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx +++ b/src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx @@ -1,4 +1,4 @@ -import "./role-binding-details.scss" +import "./role-binding-details.scss"; import React from "react"; import { t, Trans } from "@lingui/macro"; @@ -30,7 +30,7 @@ export class RoleBindingDetails extends React.Component { reaction(() => this.props.object, (obj) => { this.selectedSubjects.clear(); }) - ]) + ]); } selectSubject(subject: IRoleBindingSubject) { @@ -40,7 +40,7 @@ export class RoleBindingDetails extends React.Component { isSelected ? selectedSubjects.filter(sub => sub !== subject) // unselect : selectedSubjects.concat(subject) // select - ) + ); } @autobind() @@ -53,7 +53,7 @@ export class RoleBindingDetails extends React.Component { message: (

Remove selected bindings for {roleBinding.getName()}?

) - }) + }); } render() { @@ -106,7 +106,7 @@ export class RoleBindingDetails extends React.Component { {kind} {namespace || "-"} - ) + ); }) } @@ -119,7 +119,7 @@ export class RoleBindingDetails extends React.Component { removeTooltip={Remove selected bindings from ${name}} /> - ) + ); } } @@ -129,7 +129,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "RoleBinding", apiVersions: ["rbac.authorization.k8s.io/v1"], @@ -137,7 +137,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ @@ -146,7 +146,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "ClusterRoleBinding", apiVersions: ["rbac.authorization.k8s.io/v1"], @@ -154,4 +154,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+user-management-roles-bindings/role-bindings.store.ts b/src/renderer/components/+user-management-roles-bindings/role-bindings.store.ts index bbef0ebd31..ed3e1c0a4f 100644 --- a/src/renderer/components/+user-management-roles-bindings/role-bindings.store.ts +++ b/src/renderer/components/+user-management-roles-bindings/role-bindings.store.ts @@ -1,5 +1,5 @@ -import difference from "lodash/difference" -import uniqBy from "lodash/uniqBy" +import difference from "lodash/difference"; +import uniqBy from "lodash/uniqBy"; import { clusterRoleBindingApi, IRoleBindingSubject, RoleBinding, roleBindingApi } from "../../api/endpoints"; import { KubeObjectStore } from "../../kube-object.store"; import { autobind } from "../../utils"; @@ -7,40 +7,40 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class RoleBindingsStore extends KubeObjectStore { - api = clusterRoleBindingApi + api = clusterRoleBindingApi; subscribe() { - return super.subscribe([clusterRoleBindingApi, roleBindingApi]) + return super.subscribe([clusterRoleBindingApi, roleBindingApi]); } protected sortItems(items: RoleBinding[]) { return super.sortItems(items, [ roleBinding => roleBinding.kind, roleBinding => roleBinding.getName() - ]) + ]); } protected loadItem(params: { name: string; namespace?: string }) { - if (params.namespace) return roleBindingApi.get(params) - return clusterRoleBindingApi.get(params) + if (params.namespace) return roleBindingApi.get(params); + return clusterRoleBindingApi.get(params); } protected loadItems(namespaces?: string[]) { if (namespaces) { return Promise.all( namespaces.map(namespace => roleBindingApi.list({ namespace })) - ).then(items => items.flat()) + ).then(items => items.flat()); } else { return Promise.all([clusterRoleBindingApi.list(), roleBindingApi.list()]) - .then(items => items.flat()) + .then(items => items.flat()); } } protected async createItem(params: { name: string; namespace?: string }, data?: Partial) { if (params.namespace) { - return roleBindingApi.create(params, data) + return roleBindingApi.create(params, data); } else { - return clusterRoleBindingApi.create(params, data) + return clusterRoleBindingApi.create(params, data); } } @@ -55,7 +55,7 @@ export class RoleBindingsStore extends KubeObjectStore { if (addSubjects) { newSubjects = uniqBy(currentSubjects.concat(addSubjects), ({ kind, name, namespace }) => { return [kind, name, namespace].join("-"); - }) + }); } else if (removeSubjects) { newSubjects = difference(currentSubjects, removeSubjects); } diff --git a/src/renderer/components/+user-management-roles-bindings/role-bindings.tsx b/src/renderer/components/+user-management-roles-bindings/role-bindings.tsx index cb010a3c1b..7d9352e3bf 100644 --- a/src/renderer/components/+user-management-roles-bindings/role-bindings.tsx +++ b/src/renderer/components/+user-management-roles-bindings/role-bindings.tsx @@ -1,4 +1,4 @@ -import "./role-bindings.scss" +import "./role-bindings.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -58,6 +58,6 @@ export class RoleBindings extends React.Component { addTooltip: Create new RoleBinding, }} /> - ) + ); } } diff --git a/src/renderer/components/+user-management-roles/add-role-dialog.tsx b/src/renderer/components/+user-management-roles/add-role-dialog.tsx index 177386f72d..56766c816d 100644 --- a/src/renderer/components/+user-management-roles/add-role-dialog.tsx +++ b/src/renderer/components/+user-management-roles/add-role-dialog.tsx @@ -1,4 +1,4 @@ -import "./add-role-dialog.scss" +import "./add-role-dialog.scss"; import React from "react"; import { observable } from "mobx"; @@ -31,11 +31,11 @@ export class AddRoleDialog extends React.Component { close = () => { AddRoleDialog.close(); - } + }; reset = () => { - this.roleName = "" - } + this.roleName = ""; + }; createRole = async () => { try { @@ -46,7 +46,7 @@ export class AddRoleDialog extends React.Component { } catch (err) { Notifications.error(err.toString()); } - } + }; render() { const { ...dialogProps } = this.props; @@ -74,6 +74,6 @@ export class AddRoleDialog extends React.Component { - ) + ); } } diff --git a/src/renderer/components/+user-management-roles/index.ts b/src/renderer/components/+user-management-roles/index.ts index dd5752f4be..26eaea3b7f 100644 --- a/src/renderer/components/+user-management-roles/index.ts +++ b/src/renderer/components/+user-management-roles/index.ts @@ -1,3 +1,3 @@ -export * from "./roles" -export * from "./role-details" -export * from "./add-role-dialog" +export * from "./roles"; +export * from "./role-details"; +export * from "./add-role-dialog"; diff --git a/src/renderer/components/+user-management-roles/role-details.tsx b/src/renderer/components/+user-management-roles/role-details.tsx index fccc79eb9d..e69e6c46d7 100644 --- a/src/renderer/components/+user-management-roles/role-details.tsx +++ b/src/renderer/components/+user-management-roles/role-details.tsx @@ -1,4 +1,4 @@ -import "./role-details.scss" +import "./role-details.scss"; import React from "react"; import { Trans } from "@lingui/macro"; @@ -57,10 +57,10 @@ export class RoleDetails extends React.Component { )} - ) + ); })} - ) + ); } } @@ -70,7 +70,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Role", apiVersions: ["rbac.authorization.k8s.io/v1"], @@ -78,7 +78,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "ClusterRole", @@ -86,7 +86,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "ClusterRole", apiVersions: ["rbac.authorization.k8s.io/v1"], @@ -94,4 +94,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+user-management-roles/roles.store.ts b/src/renderer/components/+user-management-roles/roles.store.ts index e41171ee0c..d3f17e520c 100644 --- a/src/renderer/components/+user-management-roles/roles.store.ts +++ b/src/renderer/components/+user-management-roles/roles.store.ts @@ -5,40 +5,40 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class RolesStore extends KubeObjectStore { - api = clusterRoleApi + api = clusterRoleApi; subscribe() { - return super.subscribe([roleApi, clusterRoleApi]) + return super.subscribe([roleApi, clusterRoleApi]); } protected sortItems(items: Role[]) { return super.sortItems(items, [ role => role.kind, role => role.getName(), - ]) + ]); } protected loadItem(params: { name: string; namespace?: string }) { - if (params.namespace) return roleApi.get(params) - return clusterRoleApi.get(params) + if (params.namespace) return roleApi.get(params); + return clusterRoleApi.get(params); } protected loadItems(namespaces?: string[]): Promise { if (namespaces) { return Promise.all( namespaces.map(namespace => roleApi.list({ namespace })) - ).then(items => items.flat()) + ).then(items => items.flat()); } else { return Promise.all([clusterRoleApi.list(), roleApi.list()]) - .then(items => items.flat()) + .then(items => items.flat()); } } protected async createItem(params: { name: string; namespace?: string }, data?: Partial) { if (params.namespace) { - return roleApi.create(params, data) + return roleApi.create(params, data); } else { - return clusterRoleApi.create(params, data) + return clusterRoleApi.create(params, data); } } } diff --git a/src/renderer/components/+user-management-roles/roles.tsx b/src/renderer/components/+user-management-roles/roles.tsx index ca78c1d5d7..015ec2d630 100644 --- a/src/renderer/components/+user-management-roles/roles.tsx +++ b/src/renderer/components/+user-management-roles/roles.tsx @@ -1,4 +1,4 @@ -import "./roles.scss" +import "./roles.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -56,6 +56,6 @@ export class Roles extends React.Component { /> - ) + ); } } diff --git a/src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx b/src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx index d84cc01e59..ce677c3353 100644 --- a/src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx +++ b/src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx @@ -22,8 +22,8 @@ interface Props extends Partial { export class CreateServiceAccountDialog extends React.Component { @observable static isOpen = false; - @observable name = "" - @observable namespace = "default" + @observable name = ""; + @observable namespace = "default"; static open() { CreateServiceAccountDialog.isOpen = true; @@ -35,7 +35,7 @@ export class CreateServiceAccountDialog extends React.Component { close = () => { CreateServiceAccountDialog.close(); - } + }; createAccount = async () => { const { name, namespace } = this; @@ -47,12 +47,12 @@ export class CreateServiceAccountDialog extends React.Component { } catch (err) { Notifications.error(err); } - } + }; render() { const { ...dialogProps } = this.props; const { name, namespace } = this; - const header =
Create Service Account
+ const header =
Create Service Account
; return ( { - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/+user-management-service-accounts/index.ts b/src/renderer/components/+user-management-service-accounts/index.ts index fb40e7e15e..fd45e28288 100644 --- a/src/renderer/components/+user-management-service-accounts/index.ts +++ b/src/renderer/components/+user-management-service-accounts/index.ts @@ -1,3 +1,3 @@ -export * from "./service-accounts" -export * from "./service-accounts-details" -export * from "./create-service-account-dialog" \ No newline at end of file +export * from "./service-accounts"; +export * from "./service-accounts-details"; +export * from "./create-service-account-dialog"; \ No newline at end of file diff --git a/src/renderer/components/+user-management-service-accounts/service-accounts-details.tsx b/src/renderer/components/+user-management-service-accounts/service-accounts-details.tsx index 357baee9eb..d560cd9199 100644 --- a/src/renderer/components/+user-management-service-accounts/service-accounts-details.tsx +++ b/src/renderer/components/+user-management-service-accounts/service-accounts-details.tsx @@ -39,27 +39,27 @@ export class ServiceAccountsDetails extends React.Component { }); this.secrets = await Promise.all(secrets); const imagePullSecrets = serviceAccount.getImagePullSecrets().map(async({ name }) => { - return secretsStore.load({ name, namespace }).catch(_err => { return this.generateDummySecretObject(name) }); + return secretsStore.load({ name, namespace }).catch(_err => { return this.generateDummySecretObject(name); }); }); - this.imagePullSecrets = await Promise.all(imagePullSecrets) - }) + this.imagePullSecrets = await Promise.all(imagePullSecrets); + }); renderSecrets() { const { secrets } = this; if (!secrets) { - return + return ; } return secrets.map(secret => - ) + ); } renderImagePullSecrets() { const { imagePullSecrets } = this; if (!imagePullSecrets) { - return + return ; } - return this.renderSecretLinks(imagePullSecrets) + return this.renderSecretLinks(imagePullSecrets); } renderSecretLinks(secrets: Secret[]) { @@ -73,14 +73,14 @@ export class ServiceAccountsDetails extends React.Component { tooltip={Secret is not found} /> - ) + ); } return ( {secret.getName()} - ) - }) + ); + }); } generateDummySecretObject(name: string) { @@ -93,7 +93,7 @@ export class ServiceAccountsDetails extends React.Component { selfLink: null, resourceVersion: null } - }) + }); } render() { @@ -104,8 +104,8 @@ export class ServiceAccountsDetails extends React.Component { const tokens = secretsStore.items.filter(secret => secret.getNs() == serviceAccount.getNs() && secret.getAnnotations().some(annot => annot == `kubernetes.io/service-account.name: ${serviceAccount.getName()}`) - ) - const imagePullSecrets = serviceAccount.getImagePullSecrets() + ); + const imagePullSecrets = serviceAccount.getImagePullSecrets(); return (
@@ -126,7 +126,7 @@ export class ServiceAccountsDetails extends React.Component { {this.renderSecrets()}
- ) + ); } } @@ -136,7 +136,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "ServiceAccount", apiVersions: ["v1"], @@ -144,4 +144,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx b/src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx index bc75d103f7..ad3eec3d2e 100644 --- a/src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx +++ b/src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx @@ -1,4 +1,4 @@ -import "./service-accounts-secret.scss" +import "./service-accounts-secret.scss"; import React from "react"; import moment from "moment"; @@ -18,11 +18,11 @@ interface State { export class ServiceAccountsSecret extends React.Component { public state: State = { showToken: false, - } + }; renderSecretValue() { - const { secret } = this.props - const { showToken } = this.state + const { secret } = this.props; + const { showToken } = this.state; return ( <> {!showToken && ( @@ -39,7 +39,7 @@ export class ServiceAccountsSecret extends React.Component { {secret.getToken()} )} - ) + ); } render() { @@ -65,6 +65,6 @@ export class ServiceAccountsSecret extends React.Component { {type} - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/+user-management-service-accounts/service-accounts.store.ts b/src/renderer/components/+user-management-service-accounts/service-accounts.store.ts index ff958567ae..1d3faa6b1c 100644 --- a/src/renderer/components/+user-management-service-accounts/service-accounts.store.ts +++ b/src/renderer/components/+user-management-service-accounts/service-accounts.store.ts @@ -5,7 +5,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class ServiceAccountsStore extends KubeObjectStore { - api = serviceAccountsApi + api = serviceAccountsApi; protected async createItem(params: { name: string; namespace?: string }) { await super.createItem(params); diff --git a/src/renderer/components/+user-management-service-accounts/service-accounts.tsx b/src/renderer/components/+user-management-service-accounts/service-accounts.tsx index 0455a5cdc0..d612dd2376 100644 --- a/src/renderer/components/+user-management-service-accounts/service-accounts.tsx +++ b/src/renderer/components/+user-management-service-accounts/service-accounts.tsx @@ -54,7 +54,7 @@ export class ServiceAccounts extends React.Component { account.getAge(), ]} renderItemMenu={(item: ServiceAccount) => { - return + return ; }} addRemoveButtons={{ onAdd: () => CreateServiceAccountDialog.open(), @@ -63,7 +63,7 @@ export class ServiceAccounts extends React.Component { /> - ) + ); } } @@ -74,7 +74,7 @@ function ServiceAccountMenu(props: KubeObjectMenuProps) { Kubeconfig - ) + ); } kubeObjectMenuRegistry.add({ @@ -83,4 +83,4 @@ kubeObjectMenuRegistry.add({ components: { MenuItem: ServiceAccountMenu } -}) +}); diff --git a/src/renderer/components/+user-management/index.ts b/src/renderer/components/+user-management/index.ts index 8250079e60..6f29869b9b 100644 --- a/src/renderer/components/+user-management/index.ts +++ b/src/renderer/components/+user-management/index.ts @@ -1,2 +1,2 @@ -export * from "./user-management" -export * from "./user-management.route" \ No newline at end of file +export * from "./user-management"; +export * from "./user-management.route"; \ No newline at end of file diff --git a/src/renderer/components/+user-management/user-management.route.ts b/src/renderer/components/+user-management/user-management.route.ts index aa520fb128..9dc17cbbd8 100644 --- a/src/renderer/components/+user-management/user-management.route.ts +++ b/src/renderer/components/+user-management/user-management.route.ts @@ -1,23 +1,23 @@ import type { RouteProps } from "react-router"; import { buildURL, IURLParams } from "../../../common/utils/buildUrl"; -import { UserManagement } from "./user-management" +import { UserManagement } from "./user-management"; export const usersManagementRoute: RouteProps = { get path() { - return UserManagement.tabRoutes.map(({ routePath }) => routePath).flat() + return UserManagement.tabRoutes.map(({ routePath }) => routePath).flat(); } -} +}; // Routes export const serviceAccountsRoute: RouteProps = { path: "/service-accounts" -} +}; export const rolesRoute: RouteProps = { path: "/roles" -} +}; export const roleBindingsRoute: RouteProps = { path: "/role-bindings" -} +}; // Route params export interface IServiceAccountsRouteParams { @@ -31,6 +31,6 @@ export interface IRolesRouteParams { // URL-builders export const usersManagementURL = (params?: IURLParams) => serviceAccountsURL(params); -export const serviceAccountsURL = buildURL(serviceAccountsRoute.path) -export const roleBindingsURL = buildURL(roleBindingsRoute.path) -export const rolesURL = buildURL(rolesRoute.path) +export const serviceAccountsURL = buildURL(serviceAccountsRoute.path); +export const roleBindingsURL = buildURL(roleBindingsRoute.path); +export const rolesURL = buildURL(rolesRoute.path); diff --git a/src/renderer/components/+user-management/user-management.tsx b/src/renderer/components/+user-management/user-management.tsx index e7985fae6a..9c03390656 100644 --- a/src/renderer/components/+user-management/user-management.tsx +++ b/src/renderer/components/+user-management/user-management.tsx @@ -1,4 +1,4 @@ -import "./user-management.scss" +import "./user-management.scss"; import React from "react"; import { observer } from "mobx-react"; import { Trans } from "@lingui/macro"; @@ -15,7 +15,7 @@ import { isAllowedResource } from "../../../common/rbac"; export class UserManagement extends React.Component { static get tabRoutes() { const tabRoutes: TabLayoutRoute[] = []; - const query = namespaceStore.getContextParams() + const query = namespaceStore.getContextParams(); tabRoutes.push( { title: Service Accounts, @@ -35,14 +35,14 @@ export class UserManagement extends React.Component { url: rolesURL({ query }), routePath: rolesRoute.path.toString(), }, - ) + ); if (isAllowedResource("podsecuritypolicies")) { tabRoutes.push({ title: Pod Security Policies, component: PodSecurityPolicies, url: podSecurityPoliciesURL(), routePath: podSecurityPoliciesRoute.path.toString(), - }) + }); } return tabRoutes; } @@ -50,6 +50,6 @@ export class UserManagement extends React.Component { render() { return ( - ) + ); } } diff --git a/src/renderer/components/+whats-new/index.tsx b/src/renderer/components/+whats-new/index.tsx index 9f46112328..ebfdf6ff1b 100644 --- a/src/renderer/components/+whats-new/index.tsx +++ b/src/renderer/components/+whats-new/index.tsx @@ -1,2 +1,2 @@ -export * from "./whats-new.route" -export * from "./whats-new" +export * from "./whats-new.route"; +export * from "./whats-new"; diff --git a/src/renderer/components/+whats-new/whats-new.route.ts b/src/renderer/components/+whats-new/whats-new.route.ts index f989d676b7..e73fd20fca 100644 --- a/src/renderer/components/+whats-new/whats-new.route.ts +++ b/src/renderer/components/+whats-new/whats-new.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const whatsNewRoute: RouteProps = { path: "/what-s-new" -} +}; -export const whatsNewURL = buildURL(whatsNewRoute.path) +export const whatsNewURL = buildURL(whatsNewRoute.path); diff --git a/src/renderer/components/+whats-new/whats-new.tsx b/src/renderer/components/+whats-new/whats-new.tsx index c63e8f25d1..9b0df95d70 100644 --- a/src/renderer/components/+whats-new/whats-new.tsx +++ b/src/renderer/components/+whats-new/whats-new.tsx @@ -1,13 +1,13 @@ -import "./whats-new.scss" +import "./whats-new.scss"; import fs from "fs"; import path from "path"; import React from "react"; import { observer } from "mobx-react"; -import { userStore } from "../../../common/user-store" +import { userStore } from "../../../common/user-store"; import { navigate } from "../../navigation"; import { Button } from "../button"; import { Trans } from "@lingui/macro"; -import marked from "marked" +import marked from "marked"; @observer export class WhatsNew extends React.Component { @@ -16,7 +16,7 @@ export class WhatsNew extends React.Component { ok = () => { navigate("/"); userStore.saveLastSeenAppVersion(); - } + }; render() { const logo = require("../../components/icon/lens-logo.svg"); diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx index b540b6e8a6..cd8e038d90 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx @@ -30,7 +30,7 @@ export class CronJobDetails extends React.Component { render() { const { object: cronJob } = this.props; if (!cronJob) return null; - const childJobs = jobStore.getJobsByOwner(cronJob) + const childJobs = jobStore.getJobsByOwner(cronJob); return (
@@ -54,8 +54,8 @@ export class CronJobDetails extends React.Component { <> Jobs}/> {childJobs.map((job: Job) => { - const selectors = job.getSelectors() - const condition = job.getCondition() + const selectors = job.getSelectors(); + const condition = job.getCondition(); return (
@@ -77,12 +77,12 @@ export class CronJobDetails extends React.Component { }
- )}) + );}) } }
- ) + ); } } @@ -92,7 +92,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "CronJob", apiVersions: ["batch/v1"], @@ -100,4 +100,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props) => } -}) +}); diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx b/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx index 8fa77bd194..5dda5989ae 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx @@ -39,18 +39,18 @@ export class CronJobTriggerDialog extends Component { close = () => { CronJobTriggerDialog.close(); - } + }; onOpen = async () => { const { cronjob } = this; this.jobName = cronjob ? cronjob.getName() + "-manual-" + Math.random().toString(36).slice(2, 7) : ""; this.jobName = this.jobName.slice(0, 63); this.ready = true; - } + }; onClose = () => { this.ready = false; - } + }; trigger = async () => { const { cronjob } = this; @@ -72,7 +72,7 @@ export class CronJobTriggerDialog extends Component { } catch (err) { Notifications.error(err); } - } + }; renderContents() { return ( @@ -91,7 +91,7 @@ export class CronJobTriggerDialog extends Component { />
- ) + ); } render() { diff --git a/src/renderer/components/+workloads-cronjobs/cronjob.store.ts b/src/renderer/components/+workloads-cronjobs/cronjob.store.ts index b1370d2104..30915f733c 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob.store.ts +++ b/src/renderer/components/+workloads-cronjobs/cronjob.store.ts @@ -6,19 +6,19 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class CronJobStore extends KubeObjectStore { - api = cronJobApi + api = cronJobApi; getStatuses(cronJobs?: CronJob[]) { - const status = { suspended: 0, scheduled: 0 } + const status = { suspended: 0, scheduled: 0 }; cronJobs.forEach(cronJob => { if (cronJob.spec.suspend) { - status.suspended++ + status.suspended++; } else { - status.scheduled++ + status.scheduled++; } - }) - return status + }); + return status; } getActiveJobsNum(cronJob: CronJob) { diff --git a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx index ab7609de81..b5cf6d328f 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx @@ -71,10 +71,10 @@ export class CronJobs extends React.Component { cronJob.getAge(), ]} renderItemMenu={(item: CronJob) => { - return + return ; }} /> - ) + ); } } @@ -85,7 +85,7 @@ export function CronJobMenu(props: KubeObjectMenuProps) { Trigger - ) + ); } kubeObjectMenuRegistry.add({ @@ -94,4 +94,4 @@ kubeObjectMenuRegistry.add({ components: { MenuItem: CronJobMenu } -}) +}); diff --git a/src/renderer/components/+workloads-cronjobs/index.ts b/src/renderer/components/+workloads-cronjobs/index.ts index 71c59dcfee..3884050448 100644 --- a/src/renderer/components/+workloads-cronjobs/index.ts +++ b/src/renderer/components/+workloads-cronjobs/index.ts @@ -1,2 +1,2 @@ -export * from "./cronjobs" -export * from "./cronjob-details" +export * from "./cronjobs"; +export * from "./cronjob-details"; diff --git a/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx b/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx index c234fc841c..9d678c8adf 100644 --- a/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx +++ b/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx @@ -43,12 +43,12 @@ export class DaemonSetDetails extends React.Component { render() { const { object: daemonSet } = this.props; if (!daemonSet) return null; - const { spec } = daemonSet + const { spec } = daemonSet; const selectors = daemonSet.getSelectors(); - const images = daemonSet.getImages() - const nodeSelector = daemonSet.getNodeSelectors() - const childPods = daemonSetStore.getChildPods(daemonSet) - const metrics = daemonSetStore.metrics + const images = daemonSet.getImages(); + const nodeSelector = daemonSet.getNodeSelectors(); + const childPods = daemonSetStore.getChildPods(daemonSet); + const metrics = daemonSetStore.metrics; return (
{podsStore.isLoaded && ( @@ -92,7 +92,7 @@ export class DaemonSetDetails extends React.Component {
- ) + ); } } @@ -102,7 +102,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "DaemonSet", apiVersions: ["apps/v1"], @@ -110,4 +110,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); diff --git a/src/renderer/components/+workloads-daemonsets/daemonsets.store.ts b/src/renderer/components/+workloads-daemonsets/daemonsets.store.ts index 142079a365..e21bcc7548 100644 --- a/src/renderer/components/+workloads-daemonsets/daemonsets.store.ts +++ b/src/renderer/components/+workloads-daemonsets/daemonsets.store.ts @@ -7,7 +7,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class DaemonSetStore extends KubeObjectStore { - api = daemonSetApi + api = daemonSetApi; @observable metrics: IPodMetrics = null; @@ -17,24 +17,24 @@ export class DaemonSetStore extends KubeObjectStore { } getChildPods(daemonSet: DaemonSet): Pod[] { - return podsStore.getPodsByOwner(daemonSet) + return podsStore.getPodsByOwner(daemonSet); } getStatuses(daemonSets?: DaemonSet[]) { - const status = { failed: 0, pending: 0, running: 0 } + const status = { failed: 0, pending: 0, running: 0 }; daemonSets.forEach(daemonSet => { - const pods = this.getChildPods(daemonSet) + const pods = this.getChildPods(daemonSet); if (pods.some(pod => pod.getStatus() === PodStatus.FAILED)) { - status.failed++ + status.failed++; } else if (pods.some(pod => pod.getStatus() === PodStatus.PENDING)) { - status.pending++ + status.pending++; } else { - status.running++ + status.running++; } - }) - return status + }); + return status; } reset() { diff --git a/src/renderer/components/+workloads-daemonsets/daemonsets.tsx b/src/renderer/components/+workloads-daemonsets/daemonsets.tsx index e185e7f99a..a087d8a267 100644 --- a/src/renderer/components/+workloads-daemonsets/daemonsets.tsx +++ b/src/renderer/components/+workloads-daemonsets/daemonsets.tsx @@ -33,7 +33,7 @@ export class DaemonSets extends React.Component { renderNodeSelector(daemonSet: DaemonSet) { return daemonSet.getNodeSelectors().map(selector => ( - )) + )); } render() { @@ -69,7 +69,7 @@ export class DaemonSets extends React.Component { daemonSet.getAge(), ]} /> - ) + ); } } diff --git a/src/renderer/components/+workloads-daemonsets/index.ts b/src/renderer/components/+workloads-daemonsets/index.ts index 7f32ffdf2f..d007a0065d 100644 --- a/src/renderer/components/+workloads-daemonsets/index.ts +++ b/src/renderer/components/+workloads-daemonsets/index.ts @@ -1,2 +1,2 @@ -export * from "./daemonsets" -export * from "./daemonset-details" +export * from "./daemonsets"; +export * from "./daemonset-details"; diff --git a/src/renderer/components/+workloads-deployments/deployment-details.tsx b/src/renderer/components/+workloads-deployments/deployment-details.tsx index 397af77530..0c5f4f8548 100644 --- a/src/renderer/components/+workloads-deployments/deployment-details.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-details.tsx @@ -49,13 +49,13 @@ export class DeploymentDetails extends React.Component { render() { const { object: deployment } = this.props; - if (!deployment) return null - const { status, spec } = deployment - const nodeSelector = deployment.getNodeSelectors() + if (!deployment) return null; + const { status, spec } = deployment; + const nodeSelector = deployment.getNodeSelectors(); const selectors = deployment.getSelectors(); - const childPods = deploymentStore.getChildPods(deployment) - const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment) - const metrics = deploymentStore.metrics + const childPods = deploymentStore.getChildPods(deployment); + const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment); + const metrics = deploymentStore.metrics; return (
{podsStore.isLoaded && ( @@ -94,7 +94,7 @@ export class DeploymentDetails extends React.Component { Conditions} className="conditions" labelsOnly> { deployment.getConditions().map(condition => { - const { type, message, lastTransitionTime, status } = condition + const { type, message, lastTransitionTime, status } = condition; return ( {
- ) + ); } } @@ -127,7 +127,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Deployment", apiVersions: ["apps/v1"], @@ -135,4 +135,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); diff --git a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx b/src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx index 4c01032377..00aaef161e 100644 --- a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { render, waitFor, fireEvent } from '@testing-library/react'; -import '@testing-library/jest-dom/extend-expect' +import '@testing-library/jest-dom/extend-expect'; import { DeploymentScaleDialog } from "./deployment-scale-dialog"; jest.mock("../../api/endpoints"); @@ -91,7 +91,7 @@ const dummyDeployment = { toPlainObject: jest.fn(), update: jest.fn(), delete: jest.fn(), -} +}; describe('', () => { @@ -103,7 +103,7 @@ describe('', () => { it('inits with a dummy deployment with mocked current/desired scale', async () => { // mock deploymentApi.getReplicas() which will be called // when rendered. - const initReplicas = 3 + const initReplicas = 3; deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas); const { getByTestId } = render(); DeploymentScaleDialog.open(dummyDeployment); @@ -113,7 +113,7 @@ describe('', () => { const [currentScale, desiredScale] = await Promise.all([ getByTestId('current-scale'), getByTestId('desired-scale'), - ]) + ]); expect(currentScale).toHaveTextContent(`${initReplicas}`); expect(desiredScale).toHaveTextContent(`${initReplicas}`); }); @@ -121,7 +121,7 @@ describe('', () => { }); it('changes the desired scale when clicking the icon buttons +/-', async () => { - const initReplicas = 1 + const initReplicas = 1; deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas); const { getByTestId } = render(); DeploymentScaleDialog.open(dummyDeployment); @@ -130,7 +130,7 @@ describe('', () => { expect(desiredScale).toHaveTextContent(`${initReplicas}`); }); const up = await getByTestId('desired-replicas-up'); - const down = await getByTestId('desired-replicas-down') + const down = await getByTestId('desired-replicas-down'); fireEvent.click(up); expect(await getByTestId('desired-scale')).toHaveTextContent(`${initReplicas + 1}`); fireEvent.click(down); diff --git a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx b/src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx index e270729562..92ac7cfc97 100644 --- a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx @@ -39,7 +39,7 @@ export class DeploymentScaleDialog extends Component { close = () => { DeploymentScaleDialog.close(); - } + }; @computed get scaleMax() { const { currentReplicas } = this; @@ -57,15 +57,15 @@ export class DeploymentScaleDialog extends Component { }); this.desiredReplicas = this.currentReplicas; this.ready = true; - } + }; onClose = () => { this.ready = false; - } + }; onChange = (evt: React.ChangeEvent, value: number) => { this.desiredReplicas = value; - } + }; scale = async () => { const { deployment } = this; @@ -81,14 +81,14 @@ export class DeploymentScaleDialog extends Component { } catch (err) { Notifications.error(err); } - } + }; desiredReplicasUp = () => { - this.desiredReplicas < this.scaleMax && this.desiredReplicas++ - } + this.desiredReplicas < this.scaleMax && this.desiredReplicas++; + }; desiredReplicasDown = () => { - this.desiredReplicas > 1 && this.desiredReplicas-- + this.desiredReplicas > 1 && this.desiredReplicas--; }; renderContents() { @@ -126,7 +126,7 @@ export class DeploymentScaleDialog extends Component { } - ) + ); } render() { diff --git a/src/renderer/components/+workloads-deployments/deployments.store.ts b/src/renderer/components/+workloads-deployments/deployments.store.ts index 3069a84d3c..18697eab1d 100644 --- a/src/renderer/components/+workloads-deployments/deployments.store.ts +++ b/src/renderer/components/+workloads-deployments/deployments.store.ts @@ -7,7 +7,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class DeploymentStore extends KubeObjectStore { - api = deploymentApi + api = deploymentApi; @observable metrics: IPodMetrics = null; protected sortItems(items: Deployment[]) { @@ -22,26 +22,26 @@ export class DeploymentStore extends KubeObjectStore { } getStatuses(deployments?: Deployment[]) { - const status = { failed: 0, pending: 0, running: 0 } + const status = { failed: 0, pending: 0, running: 0 }; deployments.forEach(deployment => { const pods = this.getChildPods(deployment); if (pods.some(pod => pod.getStatus() === PodStatus.FAILED)) { - status.failed++ + status.failed++; } else if (pods.some(pod => pod.getStatus() === PodStatus.PENDING)) { - status.pending++ + status.pending++; } else { - status.running++ + status.running++; } - }) - return status + }); + return status; } getChildPods(deployment: Deployment) { return podsStore .getByLabel(deployment.getTemplateLabels()) - .filter(pod => pod.getNs() === deployment.getNs()) + .filter(pod => pod.getNs() === deployment.getNs()); } reset() { diff --git a/src/renderer/components/+workloads-deployments/deployments.tsx b/src/renderer/components/+workloads-deployments/deployments.tsx index fdc7348590..bb0fd59a3c 100644 --- a/src/renderer/components/+workloads-deployments/deployments.tsx +++ b/src/renderer/components/+workloads-deployments/deployments.tsx @@ -1,4 +1,4 @@ -import "./deployments.scss" +import "./deployments.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -39,17 +39,17 @@ interface Props extends RouteComponentProps { @observer export class Deployments extends React.Component { renderPods(deployment: Deployment) { - const { replicas, availableReplicas } = deployment.status - return `${availableReplicas || 0}/${replicas || 0}` + const { replicas, availableReplicas } = deployment.status; + return `${availableReplicas || 0}/${replicas || 0}`; } renderConditions(deployment: Deployment) { - const conditions = orderBy(deployment.getConditions(true), "type", "asc") + const conditions = orderBy(deployment.getConditions(true), "type", "asc"); return conditions.map(({ type, message }) => ( {type} - )) + )); } render() { @@ -88,10 +88,10 @@ export class Deployments extends React.Component { this.renderConditions(deployment), ]} renderItemMenu={(item: Deployment) => { - return + return ; }} /> - ) + ); } } @@ -110,7 +110,7 @@ export function DeploymentMenu(props: KubeObjectMenuProps) { await deploymentApi.restart({ namespace: object.getNs(), name: object.getName(), - }) + }); } catch (err) { Notifications.error(err); } @@ -126,7 +126,7 @@ export function DeploymentMenu(props: KubeObjectMenuProps) { Restart - ) + ); } kubeObjectMenuRegistry.add({ @@ -135,4 +135,4 @@ kubeObjectMenuRegistry.add({ components: { MenuItem: DeploymentMenu } -}) +}); diff --git a/src/renderer/components/+workloads-deployments/index.ts b/src/renderer/components/+workloads-deployments/index.ts index 1a8a81abb5..322a39b8e6 100644 --- a/src/renderer/components/+workloads-deployments/index.ts +++ b/src/renderer/components/+workloads-deployments/index.ts @@ -1,2 +1,2 @@ -export * from "./deployments" -export * from "./deployment-details" +export * from "./deployments"; +export * from "./deployment-details"; diff --git a/src/renderer/components/+workloads-jobs/index.ts b/src/renderer/components/+workloads-jobs/index.ts index 8389bf51cd..d4cf561141 100644 --- a/src/renderer/components/+workloads-jobs/index.ts +++ b/src/renderer/components/+workloads-jobs/index.ts @@ -1,2 +1,2 @@ -export * from "./jobs" -export * from "./job-details" +export * from "./jobs"; +export * from "./job-details"; diff --git a/src/renderer/components/+workloads-jobs/job-details.tsx b/src/renderer/components/+workloads-jobs/job-details.tsx index 8cbee901d7..48eef443be 100644 --- a/src/renderer/components/+workloads-jobs/job-details.tsx +++ b/src/renderer/components/+workloads-jobs/job-details.tsx @@ -35,12 +35,12 @@ export class JobDetails extends React.Component { render() { const { object: job } = this.props; if (!job) return null; - const selectors = job.getSelectors() - const nodeSelector = job.getNodeSelectors() - const images = job.getImages() - const childPods = jobStore.getChildPods(job) - const ownerRefs = job.getOwnerRefs() - const condition = job.getCondition() + const selectors = job.getSelectors(); + const nodeSelector = job.getNodeSelectors(); + const images = job.getImages(); + const childPods = jobStore.getChildPods(job); + const ownerRefs = job.getOwnerRefs(); + const condition = job.getCondition(); return (
@@ -70,7 +70,7 @@ export class JobDetails extends React.Component { { ownerRefs.map(ref => { const { name, kind } = ref; - const detailsUrl = getDetailsUrl(lookupApiLink(ref, job)) + const detailsUrl = getDetailsUrl(lookupApiLink(ref, job)); return (

{kind} {name} @@ -102,7 +102,7 @@ export class JobDetails extends React.Component {

- ) + ); } } @@ -112,7 +112,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Job", apiVersions: ["batch/v1"], @@ -120,4 +120,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); diff --git a/src/renderer/components/+workloads-jobs/job.store.ts b/src/renderer/components/+workloads-jobs/job.store.ts index c387e7793d..1661ee6a62 100644 --- a/src/renderer/components/+workloads-jobs/job.store.ts +++ b/src/renderer/components/+workloads-jobs/job.store.ts @@ -7,37 +7,37 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class JobStore extends KubeObjectStore { - api = jobApi + api = jobApi; getChildPods(job: Job): Pod[] { - return podsStore.getPodsByOwner(job) + return podsStore.getPodsByOwner(job); } getJobsByOwner(cronJob: CronJob) { return this.items.filter(job => job.getNs() == cronJob.getNs() && job.getOwnerRefs().find(ref => ref.name === cronJob.getName() && ref.kind === cronJob.kind) - ) + ); } getStatuses(jobs?: Job[]) { - const status = { failed: 0, pending: 0, running: 0, succeeded: 0 } + const status = { failed: 0, pending: 0, running: 0, succeeded: 0 }; jobs.forEach(job => { - const pods = this.getChildPods(job) + const pods = this.getChildPods(job); if (pods.some(pod => pod.getStatus() === PodStatus.FAILED)) { - status.failed++ + status.failed++; } else if (pods.some(pod => pod.getStatus() === PodStatus.PENDING)) { - status.pending++ + status.pending++; } else if (pods.some(pod => pod.getStatus() === PodStatus.RUNNING)) { - status.running++ + status.running++; } else { - status.succeeded++ + status.succeeded++; } - }) - return status + }); + return status; } } diff --git a/src/renderer/components/+workloads-jobs/jobs.tsx b/src/renderer/components/+workloads-jobs/jobs.tsx index 10bb99d53a..2f6a83fea0 100644 --- a/src/renderer/components/+workloads-jobs/jobs.tsx +++ b/src/renderer/components/+workloads-jobs/jobs.tsx @@ -60,9 +60,9 @@ export class Jobs extends React.Component { title: condition.type, className: kebabCase(condition.type), } - ] + ]; }} /> - ) + ); } } diff --git a/src/renderer/components/+workloads-overview/overview-statuses.tsx b/src/renderer/components/+workloads-overview/overview-statuses.tsx index ca6ad0d9ba..0bdfad1030 100644 --- a/src/renderer/components/+workloads-overview/overview-statuses.tsx +++ b/src/renderer/components/+workloads-overview/overview-statuses.tsx @@ -1,4 +1,4 @@ -import "./overview-statuses.scss" +import "./overview-statuses.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -21,14 +21,14 @@ const resources: KubeResource[] = [ "daemonsets", "jobs", "cronjobs", -] +]; @observer export class OverviewStatuses extends React.Component { @autobind() renderWorkload(resource: KubeResource): React.ReactElement { const store = workloadStores[resource]; - const items = store.getAllByNs(namespaceStore.contextNs) + const items = store.getAllByNs(namespaceStore.contextNs); return (
@@ -36,7 +36,7 @@ export class OverviewStatuses extends React.Component {
- ) + ); } render() { @@ -55,6 +55,6 @@ export class OverviewStatuses extends React.Component { {workloads} - ) + ); } } diff --git a/src/renderer/components/+workloads-overview/overview-workload-status.tsx b/src/renderer/components/+workloads-overview/overview-workload-status.tsx index dcd85d7ec9..127fce2778 100644 --- a/src/renderer/components/+workloads-overview/overview-workload-status.tsx +++ b/src/renderer/components/+workloads-overview/overview-workload-status.tsx @@ -18,10 +18,10 @@ interface Props { @observer export class OverviewWorkloadStatus extends React.Component { - @observable elem: HTMLElement + @observable elem: HTMLElement; componentDidMount() { - this.elem = findDOMNode(this) as HTMLElement + this.elem = findDOMNode(this) as HTMLElement; } getStatusColor(status: string) { @@ -29,9 +29,9 @@ export class OverviewWorkloadStatus extends React.Component { } renderChart() { - if (!this.elem) return null - const { status } = this.props - const statuses = Object.entries(status) + if (!this.elem) return null; + const { status } = this.props; + const statuses = Object.entries(status); const chartData: Partial = { labels: [] as string[], datasets: [{ @@ -39,21 +39,21 @@ export class OverviewWorkloadStatus extends React.Component { backgroundColor: [themeStore.activeTheme.colors.pieChartDefaultColor], label: "Empty" }] - } + }; if (statuses.some(([key, val]) => val > 0)) { const dataset: any = { data: [], backgroundColor: [], label: "Status", - } + }; statuses.forEach(([key, val]) => { if (val !== 0) { - dataset.data.push(val) - dataset.backgroundColor.push(this.getStatusColor(key)) - chartData.labels.push(capitalize(key) + ": " + val) + dataset.data.push(val); + dataset.backgroundColor.push(this.getStatusColor(key)); + chartData.labels.push(capitalize(key) + ": " + val); } - }) - chartData.datasets[0] = dataset + }); + chartData.datasets[0] = dataset; } const options = { elements: { @@ -61,10 +61,10 @@ export class OverviewWorkloadStatus extends React.Component { borderWidth: 0, }, }, - } + }; return ( - ) + ); } render() { @@ -74,6 +74,6 @@ export class OverviewWorkloadStatus extends React.Component { {this.renderChart()} - ) + ); } } diff --git a/src/renderer/components/+workloads-overview/overview.tsx b/src/renderer/components/+workloads-overview/overview.tsx index 9dd201cbf2..319f342151 100644 --- a/src/renderer/components/+workloads-overview/overview.tsx +++ b/src/renderer/components/+workloads-overview/overview.tsx @@ -1,4 +1,4 @@ -import "./overview.scss" +import "./overview.scss"; import React from "react"; import { observable, when } from "mobx"; @@ -17,7 +17,7 @@ import { cronJobStore } from "../+workloads-cronjobs/cronjob.store"; import { Spinner } from "../spinner"; import { Events } from "../+events"; import { KubeObjectStore } from "../../kube-object.store"; -import { isAllowedResource } from "../../../common/rbac" +import { isAllowedResource } from "../../../common/rbac"; interface Props extends RouteComponentProps { } @@ -67,7 +67,7 @@ export class WorkloadsOverview extends React.Component { renderContents() { if (!this.isReady) { - return + return ; } return ( <> @@ -78,7 +78,7 @@ export class WorkloadsOverview extends React.Component { className="box grow" /> } - ) + ); } render() { @@ -86,6 +86,6 @@ export class WorkloadsOverview extends React.Component {
{this.renderContents()}
- ) + ); } } diff --git a/src/renderer/components/+workloads-pods/container-charts.tsx b/src/renderer/components/+workloads-pods/container-charts.tsx index eeaa7cde76..fea28c8813 100644 --- a/src/renderer/components/+workloads-pods/container-charts.tsx +++ b/src/renderer/components/+workloads-pods/container-charts.tsx @@ -101,4 +101,4 @@ export const ContainerCharts = observer(() => { data={{ datasets: datasets[tabId] }} /> ); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/index.ts b/src/renderer/components/+workloads-pods/index.ts index 3b9241ecca..f3181cb3a2 100644 --- a/src/renderer/components/+workloads-pods/index.ts +++ b/src/renderer/components/+workloads-pods/index.ts @@ -1,2 +1,2 @@ -export * from "./pods" -export * from "./pod-details" \ No newline at end of file +export * from "./pods"; +export * from "./pod-details"; \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/pod-charts.tsx b/src/renderer/components/+workloads-pods/pod-charts.tsx index 39439d9678..40b2c072ed 100644 --- a/src/renderer/components/+workloads-pods/pod-charts.tsx +++ b/src/renderer/components/+workloads-pods/pod-charts.tsx @@ -128,4 +128,4 @@ export const PodCharts = observer(() => { data={{ datasets: datasets[tabId] }} /> ); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/pod-container-env.tsx b/src/renderer/components/+workloads-pods/pod-container-env.tsx index 2071c959d1..62b48cd44d 100644 --- a/src/renderer/components/+workloads-pods/pod-container-env.tsx +++ b/src/renderer/components/+workloads-pods/pod-container-env.tsx @@ -18,42 +18,42 @@ interface Props { } export const ContainerEnvironment = observer((props: Props) => { - const { container: { env, envFrom }, namespace } = props + const { container: { env, envFrom }, namespace } = props; useEffect( () => autorun(() => { env && env.forEach(variable => { - const { valueFrom } = variable + const { valueFrom } = variable; if (valueFrom && valueFrom.configMapKeyRef) { - configMapsStore.load({ name: valueFrom.configMapKeyRef.name, namespace }) + configMapsStore.load({ name: valueFrom.configMapKeyRef.name, namespace }); } - }) + }); envFrom && envFrom.forEach(item => { - const { configMapRef } = item + const { configMapRef } = item; if (configMapRef && configMapRef.name) { - configMapsStore.load({ name: configMapRef.name, namespace }) + configMapsStore.load({ name: configMapRef.name, namespace }); } - }) + }); }), [] - ) + ); const renderEnv = () => { const orderedEnv = _.sortBy(env, 'name'); return orderedEnv.map(variable => { - const { name, value, valueFrom } = variable - let secretValue = null + const { name, value, valueFrom } = variable; + let secretValue = null; if (value) { - secretValue = value + secretValue = value; } if (valueFrom) { - const { fieldRef, secretKeyRef, configMapKeyRef } = valueFrom + const { fieldRef, secretKeyRef, configMapKeyRef } = valueFrom; if (fieldRef) { - const { apiVersion, fieldPath } = fieldRef - secretValue = `fieldRef(${apiVersion}:${fieldPath})` + const { apiVersion, fieldPath } = fieldRef; + secretValue = `fieldRef(${apiVersion}:${fieldPath})`; } if (secretKeyRef) { secretValue = ( @@ -61,14 +61,14 @@ export const ContainerEnvironment = observer((props: Props) => { reference={secretKeyRef} namespace={namespace} /> - ) + ); } if (configMapKeyRef) { - const { name, key } = configMapKeyRef - const configMap = configMapsStore.getByName(name, namespace) + const { name, key } = configMapKeyRef; + const configMap = configMapsStore.getByName(name, namespace); secretValue = configMap ? configMap.data[key] : - `configMapKeyRef(${name}${key})` + `configMapKeyRef(${name}${key})`; } } @@ -76,31 +76,31 @@ export const ContainerEnvironment = observer((props: Props) => {
{name}: {secretValue}
- ) - }) - } + ); + }); + }; const renderEnvFrom = () => { const envVars = envFrom.map(vars => { - if (!vars.configMapRef || !vars.configMapRef.name) return - const configMap = configMapsStore.getByName(vars.configMapRef.name, namespace) - if (!configMap) return + if (!vars.configMapRef || !vars.configMapRef.name) return; + const configMap = configMapsStore.getByName(vars.configMapRef.name, namespace); + if (!configMap) return; return Object.entries(configMap.data).map(([name, value]) => (
{name}: {value}
- )) - }) - return _.flatten(envVars) - } + )); + }); + return _.flatten(envVars); + }; return ( Environment} className="ContainerEnvironment"> {env && renderEnv()} {envFrom && renderEnvFrom()} - ) -}) + ); +}); interface SecretKeyProps { reference: { @@ -111,20 +111,20 @@ interface SecretKeyProps { } const SecretKey = (props: SecretKeyProps) => { - const { reference: { name, key }, namespace } = props - const [loading, setLoading] = useState(false) - const [secret, setSecret] = useState() + const { reference: { name, key }, namespace } = props; + const [loading, setLoading] = useState(false); + const [secret, setSecret] = useState(); const showKey = async (evt: React.MouseEvent) => { - evt.preventDefault() - setLoading(true) + evt.preventDefault(); + setLoading(true); const secret = await secretsStore.load({ name, namespace }); - setLoading(false) - setSecret(secret) - } + setLoading(false); + setSecret(secret); + }; if (secret?.data?.[key]) { - return <>{base64.decode(secret.data[key])} + return <>{base64.decode(secret.data[key])}; } return ( @@ -137,5 +137,5 @@ const SecretKey = (props: SecretKeyProps) => { onClick={showKey} /> - ) -} + ); +}; diff --git a/src/renderer/components/+workloads-pods/pod-container-port.tsx b/src/renderer/components/+workloads-pods/pod-container-port.tsx index 9ebaed4fd7..f9e3c0b37c 100644 --- a/src/renderer/components/+workloads-pods/pod-container-port.tsx +++ b/src/renderer/components/+workloads-pods/pod-container-port.tsx @@ -1,15 +1,15 @@ -import "./pod-container-port.scss" +import "./pod-container-port.scss"; import React from "react"; import { observer } from "mobx-react"; import { t } from "@lingui/macro"; import { Pod, IPodContainer } from "../../api/endpoints"; import { _i18n } from "../../i18n"; -import { apiBase } from "../../api" +import { apiBase } from "../../api"; import { observable } from "mobx"; import { cssNames } from "../../utils"; import { Notifications } from "../notifications"; -import { Spinner } from "../spinner" +import { Spinner } from "../spinner"; interface Props { pod: Pod; @@ -28,7 +28,7 @@ export class PodContainerPort extends React.Component { const { pod, port } = this.props; this.waiting = true; try { - await apiBase.post(`/pods/${pod.getNs()}/pod/${pod.getName()}/port-forward/${port.containerPort}`, {}) + await apiBase.post(`/pods/${pod.getNs()}/pod/${pod.getName()}/port-forward/${port.containerPort}`, {}); } catch(error) { Notifications.error(error); } finally { @@ -39,7 +39,7 @@ export class PodContainerPort extends React.Component { render() { const { port } = this.props; const { name, containerPort, protocol } = port; - const text = (name ? name + ': ' : '')+`${containerPort}/${protocol}` + const text = (name ? name + ': ' : '')+`${containerPort}/${protocol}`; return (
this.portForward() }> @@ -49,6 +49,6 @@ export class PodContainerPort extends React.Component { )}
- ) + ); } } diff --git a/src/renderer/components/+workloads-pods/pod-details-affinities.tsx b/src/renderer/components/+workloads-pods/pod-details-affinities.tsx index 80b4f53396..ce7e837bcd 100644 --- a/src/renderer/components/+workloads-pods/pod-details-affinities.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-affinities.tsx @@ -12,10 +12,10 @@ interface Props { export class PodDetailsAffinities extends React.Component { render() { - const { workload } = this.props - const affinitiesNum = workload.getAffinityNumber() - const affinities = workload.getAffinity() - if (!affinitiesNum) return null + const { workload } = this.props; + const affinitiesNum = workload.getAffinityNumber(); + const affinities = workload.getAffinity(); + if (!affinitiesNum) return null; return ( Affinities} className="PodDetailsAffinities"> @@ -29,6 +29,6 @@ export class PodDetailsAffinities extends React.Component { - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/pod-details-container.tsx b/src/renderer/components/+workloads-pods/pod-details-container.tsx index df00721afd..52ed7571bd 100644 --- a/src/renderer/components/+workloads-pods/pod-details-container.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-container.tsx @@ -1,4 +1,4 @@ -import "./pod-details-container.scss" +import "./pod-details-container.scss"; import React from "react"; import { t, Trans } from "@lingui/macro"; @@ -23,7 +23,7 @@ interface Props { export class PodDetailsContainer extends React.Component { renderStatus(state: string, status: IPodContainerStatus) { - const ready = status ? status.ready : "" + const ready = status ? status.ready : ""; return ( {state}{ready ? `, ${_i18n._(t`ready`)}` : ""} @@ -41,20 +41,20 @@ export class PodDetailsContainer extends React.Component { {_i18n._(t`Started at`)}: {status.lastState.terminated.startedAt}
{_i18n._(t`Finished at`)}: {status.lastState.terminated.finishedAt}
- ) + ); } } render() { - const { pod, container, metrics } = this.props - if (!pod || !container) return null - const { name, image, imagePullPolicy, ports, volumeMounts, command, args } = container - const status = pod.getContainerStatuses().find(status => status.name === container.name) - const state = status ? Object.keys(status.state)[0] : "" - const lastState = status ? Object.keys(status.lastState)[0] : "" - const ready = status ? status.ready : "" - const liveness = pod.getLivenessProbe(container) - const readiness = pod.getReadinessProbe(container) + const { pod, container, metrics } = this.props; + if (!pod || !container) return null; + const { name, image, imagePullPolicy, ports, volumeMounts, command, args } = container; + const status = pod.getContainerStatuses().find(status => status.name === container.name); + const state = status ? Object.keys(status.state)[0] : ""; + const lastState = status ? Object.keys(status.lastState)[0] : ""; + const ready = status ? status.ready : ""; + const liveness = pod.getLivenessProbe(container); + const readiness = pod.getReadinessProbe(container); const isInitContainer = !!pod.getInitContainers().find(c => c.name == name); const metricTabs = [ CPU, @@ -93,10 +93,10 @@ export class PodDetailsContainer extends React.Component { Ports}> { ports.map((port) => { - const key = `${container.name}-port-${port.containerPort}-${port.protocol}` + const key = `${container.name}-port-${port.containerPort}-${port.protocol}`; return( - ) + ); }) } @@ -112,7 +112,7 @@ export class PodDetailsContainer extends React.Component { {mountPath} from {name} ({readOnly ? 'ro' : 'rw'}) - ) + ); }) } @@ -147,6 +147,6 @@ export class PodDetailsContainer extends React.Component { } - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/pod-details-list.tsx b/src/renderer/components/+workloads-pods/pod-details-list.tsx index ada7ff7753..111562d06a 100644 --- a/src/renderer/components/+workloads-pods/pod-details-list.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-list.tsx @@ -38,7 +38,7 @@ interface OptionalProps { export class PodDetailsList extends React.Component { static defaultProps: OptionalProps = { showTitle: true - } + }; private metricsWatcher = interval(120, () => { podsStore.loadKubeMetrics(this.props.owner.getNs()); @@ -49,13 +49,13 @@ export class PodDetailsList extends React.Component { [sortBy.namespace]: (pod: Pod) => pod.getNs(), [sortBy.cpu]: (pod: Pod) => podsStore.getPodKubeMetrics(pod).cpu, [sortBy.memory]: (pod: Pod) => podsStore.getPodKubeMetrics(pod).memory, - } + }; componentDidMount() { this.metricsWatcher.start(true); disposeOnUnmount(this, [ reaction(() => this.props.owner, () => this.metricsWatcher.restart(true)) - ]) + ]); } componentWillUnmount() { diff --git a/src/renderer/components/+workloads-pods/pod-details-statuses.tsx b/src/renderer/components/+workloads-pods/pod-details-statuses.tsx index e7c5ff9b80..0a293f39f9 100644 --- a/src/renderer/components/+workloads-pods/pod-details-statuses.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-statuses.tsx @@ -10,9 +10,9 @@ interface Props { export class PodDetailsStatuses extends React.Component { render() { - const { pods } = this.props - if (!pods.length) return null - const statuses = countBy(pods.map(pod => pod.getStatus())) + const { pods } = this.props; + if (!pods.length) return null; + const statuses = countBy(pods.map(pod => pod.getStatus())); return (
{ @@ -23,6 +23,6 @@ export class PodDetailsStatuses extends React.Component { )) }
- ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/pod-details-tolerations.tsx b/src/renderer/components/+workloads-pods/pod-details-tolerations.tsx index a9aee0d608..5b24cd5e53 100644 --- a/src/renderer/components/+workloads-pods/pod-details-tolerations.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-tolerations.tsx @@ -10,15 +10,15 @@ interface Props { export class PodDetailsTolerations extends React.Component { render() { - const { workload } = this.props - const tolerations = workload.getTolerations() - if (!tolerations.length) return null + const { workload } = this.props; + const tolerations = workload.getTolerations(); + if (!tolerations.length) return null; return ( Tolerations} className="PodDetailsTolerations"> { tolerations.map((toleration, index) => { - const { key, operator, effect, tolerationSeconds } = toleration + const { key, operator, effect, tolerationSeconds } = toleration; return (
Key}>{key} @@ -26,11 +26,11 @@ export class PodDetailsTolerations extends React.Component { {effect && Effect}>{effect}} {!!tolerationSeconds && Effect}>{tolerationSeconds}}
- ) + ); }) }
- ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/+workloads-pods/pod-details.tsx b/src/renderer/components/+workloads-pods/pod-details.tsx index ccd07a1f6f..e58808d77a 100644 --- a/src/renderer/components/+workloads-pods/pod-details.tsx +++ b/src/renderer/components/+workloads-pods/pod-details.tsx @@ -1,4 +1,4 @@ -import "./pod-details.scss" +import "./pod-details.scss"; import React from "react"; import kebabCase from "lodash/kebabCase"; @@ -106,7 +106,7 @@ export class PodDetails extends React.Component { className={cssNames({ disabled: status === "False" })} tooltip={Last transition time: {lastTransitionTime}} /> - ) + ); }) } @@ -134,7 +134,7 @@ export class PodDetails extends React.Component { } { pod.getInitContainers() && pod.getInitContainers().map(container => { - return + return ; }) } Containers}/> @@ -149,7 +149,7 @@ export class PodDetails extends React.Component { container={container} metrics={metrics} /> - ) + ); }) } @@ -159,7 +159,7 @@ export class PodDetails extends React.Component { {volumes.map(volume => { const claimName = volume.persistentVolumeClaim ? volume.persistentVolumeClaim.claimName : null; const configMap = volume.configMap ? volume.configMap.name : null; - const type = Object.keys(volume)[1] + const type = Object.keys(volume)[1]; return (
@@ -211,12 +211,12 @@ export class PodDetails extends React.Component { )}
- ) + ); })} )} - ) + ); } } @@ -226,7 +226,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: KubeObjectDetailsProps) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "Pod", @@ -235,4 +235,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: KubeObjectDetailsProps) => } -}) +}); diff --git a/src/renderer/components/+workloads-pods/pods.store.ts b/src/renderer/components/+workloads-pods/pods.store.ts index a42b5d515c..7dcfe11399 100644 --- a/src/renderer/components/+workloads-pods/pods.store.ts +++ b/src/renderer/components/+workloads-pods/pods.store.ts @@ -30,19 +30,19 @@ export class PodsStore extends KubeObjectStore { getPodsByOwner(workload: WorkloadKubeObject): Pod[] { if (!workload) return []; return this.items.filter(pod => { - const owners = pod.getOwnerRefs() - if (!owners.length) return - return owners.find(owner => owner.uid === workload.getId()) - }) + const owners = pod.getOwnerRefs(); + if (!owners.length) return; + return owners.find(owner => owner.uid === workload.getId()); + }); } getPodsByNode(node: string) { - if (!this.isLoaded) return [] - return this.items.filter(pod => pod.spec.nodeName === node) + if (!this.isLoaded) return []; + return this.items.filter(pod => pod.spec.nodeName === node); } getStatuses(pods: Pod[]) { - return countBy(pods.map(pod => pod.getStatus())) + return countBy(pods.map(pod => pod.getStatus())); } getPodKubeMetrics(pod: Pod) { @@ -57,16 +57,16 @@ export class PodsStore extends KubeObjectStore { if (!metrics) return empty; return containers.reduce((total, container) => { const metric = metrics.containers.find(item => item.name == container.name); - let cpu = "0" - let memory = "0" + let cpu = "0"; + let memory = "0"; if (metric && metric.usage) { - cpu = metric.usage.cpu || "0" - memory = metric.usage.memory || "0" + cpu = metric.usage.cpu || "0"; + memory = metric.usage.memory || "0"; } return { cpu: total.cpu + cpuUnitsToNumber(cpu), memory: total.memory + unitsToBytes(memory) - } + }; }, empty); } diff --git a/src/renderer/components/+workloads-pods/pods.tsx b/src/renderer/components/+workloads-pods/pods.tsx index 2916655a56..c72197bc09 100644 --- a/src/renderer/components/+workloads-pods/pods.tsx +++ b/src/renderer/components/+workloads-pods/pods.tsx @@ -1,4 +1,4 @@ -import "./pods.scss" +import "./pods.scss"; import React, { Fragment } from "react"; import { observer } from "mobx-react"; @@ -64,7 +64,7 @@ export class Pods extends React.Component { }} /> - ) + ); }); } @@ -113,13 +113,13 @@ export class Pods extends React.Component { {kind} - ) + ); }), pod.getQosClass(), pod.getAge(), { title: pod.getStatusMessage(), className: kebabCase(pod.getStatusMessage()) } ]} /> - ) + ); } } diff --git a/src/renderer/components/+workloads-replicasets/index.ts b/src/renderer/components/+workloads-replicasets/index.ts index 4053a1b9aa..2cf750a113 100644 --- a/src/renderer/components/+workloads-replicasets/index.ts +++ b/src/renderer/components/+workloads-replicasets/index.ts @@ -1,2 +1,2 @@ -export * from "./replicasets" -export * from "./replicaset-details" +export * from "./replicasets"; +export * from "./replicaset-details"; diff --git a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx index 469b23c8be..9eae1f9c1e 100644 --- a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx +++ b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx @@ -40,15 +40,15 @@ export class ReplicaSetDetails extends React.Component { } render() { - const { object: replicaSet } = this.props - if (!replicaSet) return null - const { metrics } = replicaSetStore - const { status } = replicaSet - const { availableReplicas, replicas } = status - const selectors = replicaSet.getSelectors() - const nodeSelector = replicaSet.getNodeSelectors() - const images = replicaSet.getImages() - const childPods = replicaSetStore.getChildPods(replicaSet) + const { object: replicaSet } = this.props; + if (!replicaSet) return null; + const { metrics } = replicaSetStore; + const { status } = replicaSet; + const { availableReplicas, replicas } = status; + const selectors = replicaSet.getSelectors(); + const nodeSelector = replicaSet.getNodeSelectors(); + const images = replicaSet.getImages(); + const childPods = replicaSetStore.getChildPods(replicaSet); return (
{podsStore.isLoaded && ( @@ -92,7 +92,7 @@ export class ReplicaSetDetails extends React.Component {
- ) + ); } } @@ -102,7 +102,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "ReplicaSet", apiVersions: ["apps/v1"], @@ -110,4 +110,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); diff --git a/src/renderer/components/+workloads-replicasets/replicasets.store.ts b/src/renderer/components/+workloads-replicasets/replicasets.store.ts index 765c58a4a8..f28c11203b 100644 --- a/src/renderer/components/+workloads-replicasets/replicasets.store.ts +++ b/src/renderer/components/+workloads-replicasets/replicasets.store.ts @@ -7,7 +7,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class ReplicaSetStore extends KubeObjectStore { - api = replicaSetApi + api = replicaSetApi; @observable metrics: IPodMetrics = null; async loadMetrics(replicaSet: ReplicaSet) { @@ -22,7 +22,7 @@ export class ReplicaSetStore extends KubeObjectStore { getReplicaSetsByOwner(deployment: Deployment) { return this.items.filter(replicaSet => !!replicaSet.getOwnerRefs().find(owner => owner.uid === deployment.getId()) - ) + ); } reset() { diff --git a/src/renderer/components/+workloads-replicasets/replicasets.tsx b/src/renderer/components/+workloads-replicasets/replicasets.tsx index 0a4e5ed7ff..41e8d9a0a9 100644 --- a/src/renderer/components/+workloads-replicasets/replicasets.tsx +++ b/src/renderer/components/+workloads-replicasets/replicasets.tsx @@ -32,7 +32,7 @@ export class ReplicaSets extends React.Component { [sortBy.namespace]: (replicaSet: ReplicaSet) => replicaSet.getNs(), [sortBy.age]: (replicaSet: ReplicaSet) => replicaSet.metadata.creationTimestamp, [sortBy.pods]: (replicaSet: ReplicaSet) => this.getPodsLength(replicaSet), - } + }; getPodsLength(replicaSet: ReplicaSet) { return replicaSetStore.getChildPods(replicaSet).length; @@ -81,7 +81,7 @@ export class ReplicaSets extends React.Component { - ) + ); }) } @@ -93,5 +93,5 @@ export class ReplicaSets extends React.Component { export function ReplicaSetMenu(props: KubeObjectMenuProps) { return ( - ) + ); } diff --git a/src/renderer/components/+workloads-statefulsets/index.ts b/src/renderer/components/+workloads-statefulsets/index.ts index 725851d22e..1cb72d701a 100644 --- a/src/renderer/components/+workloads-statefulsets/index.ts +++ b/src/renderer/components/+workloads-statefulsets/index.ts @@ -1,2 +1,2 @@ -export * from "./statefulsets" -export * from "./statefulset-details" \ No newline at end of file +export * from "./statefulsets"; +export * from "./statefulset-details"; \ No newline at end of file diff --git a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx index 2720a95a0d..faea31d2e2 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx @@ -42,12 +42,12 @@ export class StatefulSetDetails extends React.Component { render() { const { object: statefulSet } = this.props; - if (!statefulSet) return null - const images = statefulSet.getImages() - const selectors = statefulSet.getSelectors() - const nodeSelector = statefulSet.getNodeSelectors() - const childPods = statefulSetStore.getChildPods(statefulSet) - const metrics = statefulSetStore.metrics + if (!statefulSet) return null; + const images = statefulSet.getImages(); + const selectors = statefulSet.getSelectors(); + const nodeSelector = statefulSet.getNodeSelectors(); + const childPods = statefulSetStore.getChildPods(statefulSet); + const metrics = statefulSetStore.metrics; return (
{podsStore.isLoaded && ( @@ -90,7 +90,7 @@ export class StatefulSetDetails extends React.Component {
- ) + ); } } @@ -101,7 +101,7 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); kubeObjectDetailRegistry.add({ kind: "StatefulSet", @@ -110,4 +110,4 @@ kubeObjectDetailRegistry.add({ components: { Details: (props: any) => } -}) +}); diff --git a/src/renderer/components/+workloads-statefulsets/statefulset.store.ts b/src/renderer/components/+workloads-statefulsets/statefulset.store.ts index a72a9447df..719d253c87 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulset.store.ts +++ b/src/renderer/components/+workloads-statefulsets/statefulset.store.ts @@ -7,7 +7,7 @@ import { apiManager } from "../../api/api-manager"; @autobind() export class StatefulSetStore extends KubeObjectStore { - api = statefulSetApi + api = statefulSetApi; @observable metrics: IPodMetrics = null; async loadMetrics(statefulSet: StatefulSet) { @@ -16,24 +16,24 @@ export class StatefulSetStore extends KubeObjectStore { } getChildPods(statefulSet: StatefulSet) { - return podsStore.getPodsByOwner(statefulSet) + return podsStore.getPodsByOwner(statefulSet); } getStatuses(statefulSets: StatefulSet[]) { - const status = { failed: 0, pending: 0, running: 0 } + const status = { failed: 0, pending: 0, running: 0 }; statefulSets.forEach(statefulSet => { - const pods = this.getChildPods(statefulSet) + const pods = this.getChildPods(statefulSet); if (pods.some(pod => pod.getStatus() === PodStatus.FAILED)) { - status.failed++ + status.failed++; } else if (pods.some(pod => pod.getStatus() === PodStatus.PENDING)) { - status.pending++ + status.pending++; } else { - status.running++ + status.running++; } - }) - return status + }); + return status; } reset() { diff --git a/src/renderer/components/+workloads-statefulsets/statefulsets.tsx b/src/renderer/components/+workloads-statefulsets/statefulsets.tsx index 805c6b0911..e6f25ad9fe 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulsets.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulsets.tsx @@ -59,6 +59,6 @@ export class StatefulSets extends React.Component { statefulSet.getAge(), ]} /> - ) + ); } } diff --git a/src/renderer/components/+workloads/index.ts b/src/renderer/components/+workloads/index.ts index 1f2ae11149..a6e1904b84 100644 --- a/src/renderer/components/+workloads/index.ts +++ b/src/renderer/components/+workloads/index.ts @@ -1,3 +1,3 @@ -export * from "./workloads.route" -export * from "./workloads" -export * from "./workloads.stores" +export * from "./workloads.route"; +export * from "./workloads"; +export * from "./workloads.stores"; diff --git a/src/renderer/components/+workloads/workloads.route.ts b/src/renderer/components/+workloads/workloads.route.ts index 03e1f384a1..a0062e7336 100644 --- a/src/renderer/components/+workloads/workloads.route.ts +++ b/src/renderer/components/+workloads/workloads.route.ts @@ -5,32 +5,32 @@ import { Workloads } from "./workloads"; export const workloadsRoute: RouteProps = { get path() { - return Workloads.tabRoutes.map(({ routePath }) => routePath).flat() + return Workloads.tabRoutes.map(({ routePath }) => routePath).flat(); } -} +}; // Routes export const overviewRoute: RouteProps = { path: "/workloads" -} +}; export const podsRoute: RouteProps = { path: "/pods" -} +}; export const deploymentsRoute: RouteProps = { path: "/deployments" -} +}; export const daemonSetsRoute: RouteProps = { path: "/daemonsets" -} +}; export const statefulSetsRoute: RouteProps = { path: "/statefulsets" -} +}; export const jobsRoute: RouteProps = { path: "/jobs" -} +}; export const cronJobsRoute: RouteProps = { path: "/cronjobs" -} +}; // Route params export interface IWorkloadsOverviewRouteParams { @@ -56,13 +56,13 @@ export interface ICronJobsRouteParams { // URL-builders export const workloadsURL = (params?: IURLParams) => overviewURL(params); -export const overviewURL = buildURL(overviewRoute.path) -export const podsURL = buildURL(podsRoute.path) -export const deploymentsURL = buildURL(deploymentsRoute.path) -export const daemonSetsURL = buildURL(daemonSetsRoute.path) -export const statefulSetsURL = buildURL(statefulSetsRoute.path) -export const jobsURL = buildURL(jobsRoute.path) -export const cronJobsURL = buildURL(cronJobsRoute.path) +export const overviewURL = buildURL(overviewRoute.path); +export const podsURL = buildURL(podsRoute.path); +export const deploymentsURL = buildURL(deploymentsRoute.path); +export const daemonSetsURL = buildURL(daemonSetsRoute.path); +export const statefulSetsURL = buildURL(statefulSetsRoute.path); +export const jobsURL = buildURL(jobsRoute.path); +export const cronJobsURL = buildURL(cronJobsRoute.path); export const workloadURL: Partial>> = { "pods": podsURL, @@ -71,4 +71,4 @@ export const workloadURL: Partial> = { "statefulsets": statefulSetStore, "jobs": jobStore, "cronjobs": cronJobStore, -} +}; diff --git a/src/renderer/components/+workloads/workloads.tsx b/src/renderer/components/+workloads/workloads.tsx index 8c75e0b203..3cafea523d 100644 --- a/src/renderer/components/+workloads/workloads.tsx +++ b/src/renderer/components/+workloads/workloads.tsx @@ -1,4 +1,4 @@ -import "./workloads.scss" +import "./workloads.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -13,7 +13,7 @@ import { DaemonSets } from "../+workloads-daemonsets"; import { StatefulSets } from "../+workloads-statefulsets"; import { Jobs } from "../+workloads-jobs"; import { CronJobs } from "../+workloads-cronjobs"; -import { isAllowedResource } from "../../../common/rbac" +import { isAllowedResource } from "../../../common/rbac"; @observer export class Workloads extends React.Component { @@ -26,14 +26,14 @@ export class Workloads extends React.Component { url: overviewURL({ query }), routePath: overviewRoute.path.toString() } - ] + ]; if (isAllowedResource("pods")) { routes.push({ title: Pods, component: Pods, url: podsURL({ query }), routePath: podsRoute.path.toString() - }) + }); } if (isAllowedResource("deployments")) { routes.push({ @@ -41,7 +41,7 @@ export class Workloads extends React.Component { component: Deployments, url: deploymentsURL({ query }), routePath: deploymentsRoute.path.toString(), - }) + }); } if (isAllowedResource("daemonsets")) { routes.push({ @@ -49,7 +49,7 @@ export class Workloads extends React.Component { component: DaemonSets, url: daemonSetsURL({ query }), routePath: daemonSetsRoute.path.toString(), - }) + }); } if (isAllowedResource("statefulsets")) { routes.push({ @@ -57,7 +57,7 @@ export class Workloads extends React.Component { component: StatefulSets, url: statefulSetsURL({ query }), routePath: statefulSetsRoute.path.toString(), - }) + }); } if (isAllowedResource("jobs")) { routes.push({ @@ -65,7 +65,7 @@ export class Workloads extends React.Component { component: Jobs, url: jobsURL({ query }), routePath: jobsRoute.path.toString(), - }) + }); } if (isAllowedResource("cronjobs")) { routes.push({ @@ -73,7 +73,7 @@ export class Workloads extends React.Component { component: CronJobs, url: cronJobsURL({ query }), routePath: cronJobsRoute.path.toString(), - }) + }); } return routes; } @@ -81,6 +81,6 @@ export class Workloads extends React.Component { render() { return ( - ) + ); } } diff --git a/src/renderer/components/+workspaces/index.ts b/src/renderer/components/+workspaces/index.ts index 6aa0afedd3..db23faa3be 100644 --- a/src/renderer/components/+workspaces/index.ts +++ b/src/renderer/components/+workspaces/index.ts @@ -1,2 +1,2 @@ -export * from "./workspaces.route" -export * from "./workspaces" +export * from "./workspaces.route"; +export * from "./workspaces"; diff --git a/src/renderer/components/+workspaces/workspace-menu.tsx b/src/renderer/components/+workspaces/workspace-menu.tsx index 1979d3a3ad..78e61f87aa 100644 --- a/src/renderer/components/+workspaces/workspace-menu.tsx +++ b/src/renderer/components/+workspaces/workspace-menu.tsx @@ -1,4 +1,4 @@ -import "./workspace-menu.scss" +import "./workspace-menu.scss"; import React from "react"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; @@ -43,9 +43,9 @@ export class WorkspaceMenu extends React.Component { {name} - ) + ); })} - ) + ); } } diff --git a/src/renderer/components/+workspaces/workspaces.route.ts b/src/renderer/components/+workspaces/workspaces.route.ts index 37c1239e6c..2429c5315e 100644 --- a/src/renderer/components/+workspaces/workspaces.route.ts +++ b/src/renderer/components/+workspaces/workspaces.route.ts @@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl"; export const workspacesRoute: RouteProps = { path: "/workspaces" -} +}; -export const workspacesURL = buildURL(workspacesRoute.path) +export const workspacesURL = buildURL(workspacesRoute.path); diff --git a/src/renderer/components/+workspaces/workspaces.tsx b/src/renderer/components/+workspaces/workspaces.tsx index 4442a772e8..459f095cec 100644 --- a/src/renderer/components/+workspaces/workspaces.tsx +++ b/src/renderer/components/+workspaces/workspaces.tsx @@ -1,11 +1,11 @@ -import "./workspaces.scss" +import "./workspaces.scss"; import React, { Fragment } from "react"; import { observer } from "mobx-react"; import { computed, observable, toJS } from "mobx"; import { t, Trans } from "@lingui/macro"; import { WizardLayout } from "../layout/wizard-layout"; import { Workspace, WorkspaceId, workspaceStore } from "../../../common/workspace-store"; -import { v4 as uuid } from "uuid" +import { v4 as uuid } from "uuid"; import { _i18n } from "../../i18n"; import { ConfirmDialog } from "../confirm-dialog"; import { Icon } from "../icon"; @@ -19,10 +19,10 @@ export class Workspaces extends React.Component { @observable editingWorkspaces = observable.map(); @computed get workspaces(): Workspace[] { - const currentWorkspaces: Map = new Map() + const currentWorkspaces: Map = new Map(); workspaceStore.workspacesList.forEach((w) => { - currentWorkspaces.set(w.id, w) - }) + currentWorkspaces.set(w.id, w); + }); const allWorkspaces = new Map([ ...currentWorkspaces, ...this.editingWorkspaces, @@ -41,7 +41,7 @@ export class Workspaces extends React.Component { A single workspaces contains a list of clusters and their full configuration.

- ) + ); } saveWorkspace = (id: WorkspaceId) => { @@ -54,7 +54,7 @@ export class Workspaces extends React.Component { if (workspaceStore.addWorkspace(workspace)) { this.clearEditing(id); } - } + }; addWorkspace = () => { const workspaceId = uuid(); @@ -62,17 +62,17 @@ export class Workspaces extends React.Component { id: workspaceId, name: "", description: "" - })) - } + })); + }; editWorkspace = (id: WorkspaceId) => { const workspace = workspaceStore.getById(id); this.editingWorkspaces.set(id, toJS(workspace)); - } + }; clearEditing = (id: WorkspaceId) => { this.editingWorkspaces.delete(id); - } + }; removeWorkspace = (id: WorkspaceId) => { const workspace = workspaceStore.getById(id); @@ -96,8 +96,8 @@ export class Workspaces extends React.Component {

), - }) - } + }); + }; onInputKeypress = (evt: React.KeyboardEvent, workspaceId: WorkspaceId) => { if (evt.key == 'Enter') { @@ -106,7 +106,7 @@ export class Workspaces extends React.Component { evt.currentTarget.focus(); this.saveWorkspace(workspaceId); } - } + }; render() { return ( @@ -120,7 +120,7 @@ export class Workspaces extends React.Component { const isDefault = workspaceStore.isDefault(workspaceId); const isEditing = this.editingWorkspaces.has(workspaceId); const editingWorkspace = this.editingWorkspaces.get(workspaceId); - const managed = !!ownerRef + const managed = !!ownerRef; const className = cssNames("workspace flex gaps align-center", { active: isActive, editing: isEditing, @@ -129,7 +129,7 @@ export class Workspaces extends React.Component { const existenceValidator: InputValidator = { message: () => `Workspace '${name}' already exists`, validate: value => !workspaceStore.getByName(value.trim()) - } + }; return (
{!isEditing && ( @@ -186,7 +186,7 @@ export class Workspaces extends React.Component { )}
- ) + ); })} - ) - }) + ); + }); } render() { @@ -47,6 +47,6 @@ export class AddRemoveButtons extends React.PureComponent
{this.renderButtons()}
- ) + ); } } diff --git a/src/renderer/components/add-remove-buttons/index.ts b/src/renderer/components/add-remove-buttons/index.ts index bdd0ada883..825c59d7d2 100644 --- a/src/renderer/components/add-remove-buttons/index.ts +++ b/src/renderer/components/add-remove-buttons/index.ts @@ -1 +1 @@ -export * from "./add-remove-buttons" \ No newline at end of file +export * from "./add-remove-buttons"; \ No newline at end of file diff --git a/src/renderer/components/animate/animate.tsx b/src/renderer/components/animate/animate.tsx index 6ee4833770..660afcd915 100644 --- a/src/renderer/components/animate/animate.tsx +++ b/src/renderer/components/animate/animate.tsx @@ -43,7 +43,7 @@ export class Animate extends React.Component { delay: Animate.VISIBILITY_DELAY_MS, fireImmediately: true, }) - ]) + ]); } enter() { diff --git a/src/renderer/components/animate/index.ts b/src/renderer/components/animate/index.ts index bbc80b32fa..a4e4547423 100644 --- a/src/renderer/components/animate/index.ts +++ b/src/renderer/components/animate/index.ts @@ -1 +1 @@ -export * from './animate' \ No newline at end of file +export * from './animate'; \ No newline at end of file diff --git a/src/renderer/components/app-init/app-init.tsx b/src/renderer/components/app-init/app-init.tsx index e5a740ebc4..42353872fc 100644 --- a/src/renderer/components/app-init/app-init.tsx +++ b/src/renderer/components/app-init/app-init.tsx @@ -1,6 +1,6 @@ -import "./app-init.scss" +import "./app-init.scss"; -import React from "react" +import React from "react"; import { render } from "react-dom"; import { t } from "@lingui/macro"; import { CubeSpinner } from "../spinner"; @@ -46,6 +46,6 @@ export class AppInit extends React.Component { - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx index f05ec8a7a8..185a9650fa 100755 --- a/src/renderer/components/app.tsx +++ b/src/renderer/components/app.tsx @@ -36,7 +36,7 @@ import logger from "../../main/logger"; import { webFrame } from "electron"; import { clusterPageRegistry } from "../../extensions/registries/page-registry"; import { extensionLoader } from "../../extensions/extension-loader"; -import { appEventBus } from "../../common/event-bus" +import { appEventBus } from "../../common/event-bus"; import { requestMain } from "../../common/ipc"; import whatInput from 'what-input'; import { clusterSetFrameIdHandler } from "../../common/cluster-ipc"; @@ -46,10 +46,10 @@ export class App extends React.Component { static async init() { const frameId = webFrame.routingId; const clusterId = getHostedClusterId(); - logger.info(`[APP]: Init dashboard, clusterId=${clusterId}, frameId=${frameId}`) - await Terminal.preloadFonts() + logger.info(`[APP]: Init dashboard, clusterId=${clusterId}, frameId=${frameId}`); + await Terminal.preloadFonts(); - await requestMain(clusterSetFrameIdHandler, clusterId, frameId) + await requestMain(clusterSetFrameIdHandler, clusterId, frameId); await getHostedCluster().whenReady; // cluster.activate() is done at this point extensionLoader.loadOnClusterRenderer(); appEventBus.emit({ @@ -58,11 +58,11 @@ export class App extends React.Component { params: { clusterId: clusterId } - }) + }); window.addEventListener("online", () => { - window.location.reload() - }) - whatInput.ask() // Start to monitor user input device + window.location.reload(); + }); + whatInput.ask(); // Start to monitor user input device } get startURL() { @@ -74,8 +74,8 @@ export class App extends React.Component { renderExtensionRoutes() { return clusterPageRegistry.getItems().map(({ components: { Page }, exact, routePath }) => { - return - }) + return ; + }); } render() { @@ -111,6 +111,6 @@ export class App extends React.Component { - ) + ); } } diff --git a/src/renderer/components/badge/badge.tsx b/src/renderer/components/badge/badge.tsx index 5fd80afe2a..ea2d9dffa6 100644 --- a/src/renderer/components/badge/badge.tsx +++ b/src/renderer/components/badge/badge.tsx @@ -1,4 +1,4 @@ -import "./badge.scss" +import "./badge.scss"; import React from "react"; import { cssNames } from "../../utils/cssNames"; @@ -18,6 +18,6 @@ export class Badge extends React.Component { {label} {children} - + ; } } diff --git a/src/renderer/components/badge/index.ts b/src/renderer/components/badge/index.ts index 051fa6ea23..80844a4e3f 100644 --- a/src/renderer/components/badge/index.ts +++ b/src/renderer/components/badge/index.ts @@ -1 +1 @@ -export * from "./badge" +export * from "./badge"; diff --git a/src/renderer/components/button/button.tsx b/src/renderer/components/button/button.tsx index 65aa3a979e..ee73195509 100644 --- a/src/renderer/components/button/button.tsx +++ b/src/renderer/components/button/button.tsx @@ -45,7 +45,7 @@ export class Button extends React.PureComponent { this.link = e}> {btnContent} - ) + ); } // render as button @@ -53,6 +53,6 @@ export class Button extends React.PureComponent { - ) + ); } } diff --git a/src/renderer/components/button/index.ts b/src/renderer/components/button/index.ts index 14757e7223..eaf5eea7f1 100644 --- a/src/renderer/components/button/index.ts +++ b/src/renderer/components/button/index.ts @@ -1 +1 @@ -export * from './button' +export * from './button'; diff --git a/src/renderer/components/chart/background-block.plugin.ts b/src/renderer/components/chart/background-block.plugin.ts index c9c170ff29..1d39f71aed 100644 --- a/src/renderer/components/chart/background-block.plugin.ts +++ b/src/renderer/components/chart/background-block.plugin.ts @@ -6,7 +6,7 @@ const defaultOptions = { coverBars: 3, borderColor: "#44474A", backgroundColor: "#00000033" -} +}; export const BackgroundBlock = { options: {}, @@ -19,7 +19,7 @@ export const BackgroundBlock = { this.options = { ...defaultOptions, ...this.getOptions(chart) - } + }; }, beforeDraw(chart: ChartJS) { @@ -39,4 +39,4 @@ export const BackgroundBlock = { ctx.stroke(); ctx.restore(); } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/renderer/components/chart/bar-chart.tsx b/src/renderer/components/chart/bar-chart.tsx index b2c7547bc5..898e52969b 100644 --- a/src/renderer/components/chart/bar-chart.tsx +++ b/src/renderer/components/chart/bar-chart.tsx @@ -31,7 +31,7 @@ export class BarChart extends React.Component { const getBarColor: Scriptable = ({ dataset }) => { const color = dataset.borderColor; return Color(color).alpha(0.2).string(); - } + }; // Remove empty sets and insert default data const chartData: ChartData = { @@ -45,7 +45,7 @@ export class BarChart extends React.Component { barPercentage: 1, categoryPercentage: 1, ...item - } + }; }) }; @@ -109,15 +109,15 @@ export class BarChart extends React.Component { position: "cursor", callbacks: { title: tooltipItems => { - const now = new Date().getTime() + const now = new Date().getTime(); if (new Date(tooltipItems[0].xLabel).getTime() > now) return ""; - return `${tooltipItems[0].xLabel}` + return `${tooltipItems[0].xLabel}`; }, labelColor: ({ datasetIndex }) => { return { borderColor: "darkgray", backgroundColor: chartData.datasets[datasetIndex].borderColor as string - } + }; } } }, @@ -137,7 +137,7 @@ export class BarChart extends React.Component { }; const options = merge(barOptions, customOptions); if (chartData.datasets.length == 0) { - return + return ; } return ( { plugins={plugins} {...settings} /> - ) + ); } } @@ -180,7 +180,7 @@ export const memoryOptions: ChartOptions = { } } } -} +}; // Default options for all charts with cpu units or other decimal numbers export const cpuOptions: ChartOptions = { @@ -206,4 +206,4 @@ export const cpuOptions: ChartOptions = { } } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/renderer/components/chart/chart.tsx b/src/renderer/components/chart/chart.tsx index a5fa4b9706..5de0c9cf44 100644 --- a/src/renderer/components/chart/chart.tsx +++ b/src/renderer/components/chart/chart.tsx @@ -51,92 +51,92 @@ const defaultProps: Partial = { export class Chart extends React.Component { static defaultProps = defaultProps as object; - private canvas = React.createRef() - private chart: ChartJS + private canvas = React.createRef(); + private chart: ChartJS; // ChartJS adds _meta field to any data object passed to it. // We clone new data prop into currentChartData to compare props and prevProps - private currentChartData: ChartData + private currentChartData: ChartData; componentDidMount() { - const { showChart } = this.props - if (!showChart) return - this.renderChart() + const { showChart } = this.props; + if (!showChart) return; + this.renderChart(); } componentDidUpdate() { - const { showChart, redraw } = this.props + const { showChart, redraw } = this.props; if (redraw) { - this.chart.destroy() - this.renderChart() - return + this.chart.destroy(); + this.renderChart(); + return; } if (showChart) { - if (!this.chart) this.renderChart() - else this.updateChart() + if (!this.chart) this.renderChart(); + else this.updateChart(); } } memoizeDataProps() { - const { data } = this.props + const { data } = this.props; this.currentChartData = { ...data, datasets: data.datasets && data.datasets.map(set => { return { ...set - } + }; }) - } + }; } updateChart() { - const { options } = this.props + const { options } = this.props; - if (!this.chart) return + if (!this.chart) return; - this.chart.options = ChartJS.helpers.configMerge(this.chart.options, options) + this.chart.options = ChartJS.helpers.configMerge(this.chart.options, options); - this.memoizeDataProps() + this.memoizeDataProps(); - const datasets: ChartDataSets[] = this.chart.config.data.datasets - const nextDatasets: ChartDataSets[] = this.currentChartData.datasets || [] + const datasets: ChartDataSets[] = this.chart.config.data.datasets; + const nextDatasets: ChartDataSets[] = this.currentChartData.datasets || []; // Remove stale datasets if they're not available in nextDatasets if (datasets.length > nextDatasets.length) { const sets = [...datasets]; sets.forEach(set => { if (!nextDatasets.find(next => next.id === set.id)) { - remove(datasets, (item => item.id === set.id)) + remove(datasets, (item => item.id === set.id)); } - }) + }); } // Mutating inner chart datasets to enable seamless transitions nextDatasets.forEach((next, datasetIndex) => { - const index = datasets.findIndex(set => set.id === next.id) + const index = datasets.findIndex(set => set.id === next.id); if (index !== -1) { - datasets[index].data = datasets[index].data.slice() // "Clean" mobx observables data to use in ChartJS - datasets[index].data.splice(next.data.length) + datasets[index].data = datasets[index].data.slice(); // "Clean" mobx observables data to use in ChartJS + datasets[index].data.splice(next.data.length); next.data.forEach((point: any, dataIndex: number) => { - datasets[index].data[dataIndex] = next.data[dataIndex] - }) + datasets[index].data[dataIndex] = next.data[dataIndex]; + }); // Merge other fields - const { data, ...props } = next + const { data, ...props } = next; datasets[index] = { ...datasets[index], ...props - } + }; } else { - datasets[datasetIndex] = next + datasets[datasetIndex] = next; } - }) - this.chart.update() + }); + this.chart.update(); } renderLegend() { - if (!this.props.showLegend) return null - const { data, legendColors } = this.props - const { labels, datasets } = data + if (!this.props.showLegend) return null; + const { data, legendColors } = this.props; + const { labels, datasets } = data; const labelElem = (title: string, color: string, tooltip?: string) => ( { )} tooltip={tooltip} /> - ) + ); return (
{labels && labels.map((label: string, index) => { - const { backgroundColor } = datasets[0] as any - const color = legendColors ? legendColors[index] : backgroundColor[index] - return labelElem(label, color) + const { backgroundColor } = datasets[0] as any; + const color = legendColors ? legendColors[index] : backgroundColor[index]; + return labelElem(label, color); })} {!labels && datasets.map(({ borderColor, label, tooltip }) => labelElem(label, borderColor as any, tooltip) )}
- ) + ); } renderChart() { - const { type, options, plugins } = this.props - this.memoizeDataProps() + const { type, options, plugins } = this.props; + this.memoizeDataProps(); this.chart = new ChartJS(this.canvas.current, { type, plugins, @@ -177,11 +177,11 @@ export class Chart extends React.Component { }, }, data: this.currentChartData, - }) + }); } render() { - const { width, height, showChart, title, className } = this.props + const { width, height, showChart, title, className } = this.props; return ( <>
@@ -199,6 +199,6 @@ export class Chart extends React.Component { {this.renderLegend()}
- ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/chart/index.ts b/src/renderer/components/chart/index.ts index 920ff6c53e..a9db66c298 100644 --- a/src/renderer/components/chart/index.ts +++ b/src/renderer/components/chart/index.ts @@ -1,3 +1,3 @@ -export * from "./chart" -export * from "./pie-chart" -export * from "./bar-chart" \ No newline at end of file +export * from "./chart"; +export * from "./pie-chart"; +export * from "./bar-chart"; \ No newline at end of file diff --git a/src/renderer/components/chart/pie-chart.tsx b/src/renderer/components/chart/pie-chart.tsx index d5a7501ee6..c2d9473f06 100644 --- a/src/renderer/components/chart/pie-chart.tsx +++ b/src/renderer/components/chart/pie-chart.tsx @@ -12,9 +12,9 @@ interface Props extends ChartProps { @observer export class PieChart extends React.Component { render() { - const { data, className, options, ...chartProps } = this.props + const { data, className, options, ...chartProps } = this.props; const { contentColor } = themeStore.activeTheme.colors; - const cutouts = [88, 76, 63] + const cutouts = [88, 76, 63]; const opts: ChartOptions = this.props.showChart === false ? {} : { maintainAspectRatio: false, tooltips: { @@ -22,9 +22,9 @@ export class PieChart extends React.Component { callbacks: { title: () => "", label: (tooltipItem, data) => { - const dataset: any = data["datasets"][tooltipItem.datasetIndex] - const metaData = Object.values<{ total: number }>(dataset["_meta"])[0] - const percent = Math.round((dataset["data"][tooltipItem["index"]] / metaData.total) * 100) + const dataset: any = data["datasets"][tooltipItem.datasetIndex]; + const metaData = Object.values<{ total: number }>(dataset["_meta"])[0]; + const percent = Math.round((dataset["data"][tooltipItem["index"]] / metaData.total) * 100); if (isNaN(percent)) return "N/A"; return percent + "%"; }, @@ -45,7 +45,7 @@ export class PieChart extends React.Component { cutoutPercentage: cutouts[data.datasets.length - 1] || 50, responsive: true, ...options - } + }; return ( { options={opts} {...chartProps} /> - ) + ); } } diff --git a/src/renderer/components/chart/useRealTimeMetrics.ts b/src/renderer/components/chart/useRealTimeMetrics.ts index 96a4118dfa..7983d38b00 100644 --- a/src/renderer/components/chart/useRealTimeMetrics.ts +++ b/src/renderer/components/chart/useRealTimeMetrics.ts @@ -3,12 +3,12 @@ import { useState, useEffect } from "react"; import { useInterval } from "../../hooks"; type IMetricValues = [number, string][]; -type IChartData = { x: number; y: string }[] +type IChartData = { x: number; y: string }[]; const defaultParams = { fetchInterval: 15, updateInterval: 5 -} +}; export function useRealTimeMetrics(metrics: IMetricValues, chartData: IChartData, params = defaultParams) { const [index, setIndex] = useState(0); diff --git a/src/renderer/components/chart/zebra-stripes.plugin.ts b/src/renderer/components/chart/zebra-stripes.plugin.ts index 8b3af6571c..6af01c00de 100644 --- a/src/renderer/components/chart/zebra-stripes.plugin.ts +++ b/src/renderer/components/chart/zebra-stripes.plugin.ts @@ -9,7 +9,7 @@ const defaultOptions = { interval: 61, stripeMinutes: 10, stripeColor: "#ffffff08", -} +}; export const ZebraStripes = { updated: null as Moment, // timestamp which all stripe movements based on @@ -62,7 +62,7 @@ export const ZebraStripes = { this.options = { ...defaultOptions, ...this.getOptions(chart) - } + }; this.updated = this.getLastUpdate(chart); }, @@ -92,4 +92,4 @@ export const ZebraStripes = { cover.style.backgroundPositionX = -step * minutes + "px"; } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/renderer/components/checkbox/checkbox.tsx b/src/renderer/components/checkbox/checkbox.tsx index 64a356ff3a..5d2eeafc89 100644 --- a/src/renderer/components/checkbox/checkbox.tsx +++ b/src/renderer/components/checkbox/checkbox.tsx @@ -1,5 +1,5 @@ -import './checkbox.scss' -import React from 'react' +import './checkbox.scss'; +import React from 'react'; import { autobind, cssNames } from "../../utils"; export interface CheckboxProps { @@ -18,7 +18,7 @@ export class Checkbox extends React.PureComponent { @autobind() onChange(evt: React.ChangeEvent) { if (this.props.onChange) { - this.props.onChange(this.input.checked, evt) + this.props.onChange(this.input.checked, evt); } } diff --git a/src/renderer/components/checkbox/index.ts b/src/renderer/components/checkbox/index.ts index 527ce01c6c..7d2e810506 100644 --- a/src/renderer/components/checkbox/index.ts +++ b/src/renderer/components/checkbox/index.ts @@ -1 +1 @@ -export * from './checkbox' \ No newline at end of file +export * from './checkbox'; \ No newline at end of file diff --git a/src/renderer/components/cluster-icon/cluster-icon.tsx b/src/renderer/components/cluster-icon/cluster-icon.tsx index 34fbb9ebf8..d3e7f05eee 100644 --- a/src/renderer/components/cluster-icon/cluster-icon.tsx +++ b/src/renderer/components/cluster-icon/cluster-icon.tsx @@ -1,4 +1,4 @@ -import "./cluster-icon.scss" +import "./cluster-icon.scss"; import React, { DOMAttributes } from "react"; import { observer } from "mobx-react"; diff --git a/src/renderer/components/cluster-icon/index.ts b/src/renderer/components/cluster-icon/index.ts index 2915038d8e..4e1858939f 100644 --- a/src/renderer/components/cluster-icon/index.ts +++ b/src/renderer/components/cluster-icon/index.ts @@ -1 +1 @@ -export * from "./cluster-icon" \ No newline at end of file +export * from "./cluster-icon"; \ No newline at end of file diff --git a/src/renderer/components/cluster-manager/bottom-bar.tsx b/src/renderer/components/cluster-manager/bottom-bar.tsx index 7302469a2a..55a5aba81c 100644 --- a/src/renderer/components/cluster-manager/bottom-bar.tsx +++ b/src/renderer/components/cluster-manager/bottom-bar.tsx @@ -1,4 +1,4 @@ -import "./bottom-bar.scss" +import "./bottom-bar.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -23,10 +23,10 @@ export class BottomBar extends React.Component {
{statusBarRegistry.getItems().map(({ item }, index) => { if (!item) return; - return {item} + return {item}; })}
- ) + ); } } diff --git a/src/renderer/components/cluster-manager/cluster-manager.tsx b/src/renderer/components/cluster-manager/cluster-manager.tsx index 1522376c3e..b27e088f84 100644 --- a/src/renderer/components/cluster-manager/cluster-manager.tsx +++ b/src/renderer/components/cluster-manager/cluster-manager.tsx @@ -1,4 +1,4 @@ -import "./cluster-manager.scss" +import "./cluster-manager.scss"; import React from "react"; import { Redirect, Route, Switch } from "react-router"; @@ -37,7 +37,7 @@ export class ClusterManager extends React.Component { fireImmediately: true, equals: comparer.shallow, }), - ]) + ]); } componentWillUnmount() { @@ -51,9 +51,9 @@ export class ClusterManager extends React.Component { params: { clusterId: activeClusterId } - }) + }); } - return landingURL() + return landingURL(); } render() { @@ -70,7 +70,7 @@ export class ClusterManager extends React.Component { {globalPageRegistry.getItems().map(({ routePath, exact, components: { Page } }) => { - return + return ; })} @@ -78,6 +78,6 @@ export class ClusterManager extends React.Component { - ) + ); } } diff --git a/src/renderer/components/cluster-manager/cluster-status.tsx b/src/renderer/components/cluster-manager/cluster-status.tsx index f8d76395bc..bd8be870c2 100644 --- a/src/renderer/components/cluster-manager/cluster-status.tsx +++ b/src/renderer/components/cluster-manager/cluster-status.tsx @@ -1,6 +1,6 @@ import type { KubeAuthProxyLog } from "../../../main/kube-auth-proxy"; -import "./cluster-status.scss" +import "./cluster-status.scss"; import React from "react"; import { observer } from "mobx-react"; import { ipcRenderer } from "electron"; @@ -38,7 +38,7 @@ export class ClusterStatus extends React.Component { data: res.data.trimRight(), error: res.error, }); - }) + }); if (this.cluster.disconnected) { await this.activateCluster(); } @@ -49,15 +49,15 @@ export class ClusterStatus extends React.Component { } activateCluster = async (force = false) => { - await requestMain(clusterActivateHandler, this.props.clusterId, force) - } + await requestMain(clusterActivateHandler, this.props.clusterId, force); + }; reconnect = async () => { - this.authOutput = [] + this.authOutput = []; this.isReconnecting = true; await this.activateCluster(true); this.isReconnecting = false; - } + }; renderContent() { const { authOutput, cluster, hasErrors } = this; @@ -69,7 +69,7 @@ export class ClusterStatus extends React.Component {
             

{this.isReconnecting ? "Reconnecting..." : "Connecting..."}

{authOutput.map(({ data, error }, index) => { - return

{data}

+ return

{data}

; })}
@@ -83,7 +83,7 @@ export class ClusterStatus extends React.Component {
           {authOutput.map(({ data, error }, index) => {
-            return 

{data}

+ return

{data}

; })}
{failureReason && ( diff --git a/src/renderer/components/cluster-manager/cluster-view.route.ts b/src/renderer/components/cluster-manager/cluster-view.route.ts index bb66f56005..f31077a571 100644 --- a/src/renderer/components/cluster-manager/cluster-view.route.ts +++ b/src/renderer/components/cluster-manager/cluster-view.route.ts @@ -8,6 +8,6 @@ export interface IClusterViewRouteParams { export const clusterViewRoute: RouteProps = { exact: true, path: "/cluster/:clusterId", -} +}; -export const clusterViewURL = buildURL(clusterViewRoute.path) +export const clusterViewURL = buildURL(clusterViewRoute.path); diff --git a/src/renderer/components/cluster-manager/cluster-view.tsx b/src/renderer/components/cluster-manager/cluster-view.tsx index 613f8ab708..bbf1ba6533 100644 --- a/src/renderer/components/cluster-manager/cluster-view.tsx +++ b/src/renderer/components/cluster-manager/cluster-view.tsx @@ -1,4 +1,4 @@ -import "./cluster-view.scss" +import "./cluster-view.scss"; import React from "react"; import { reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; @@ -27,18 +27,18 @@ export class ClusterView extends React.Component { reaction(() => this.clusterId, clusterId => clusterStore.setActive(clusterId), { fireImmediately: true, }) - ]) + ]); } render() { const { cluster } = this; - const showStatus = cluster && (!cluster.available || !hasLoadedView(cluster.id) || !cluster.ready) + const showStatus = cluster && (!cluster.available || !hasLoadedView(cluster.id) || !cluster.ready); return (
{showStatus && ( )}
- ) + ); } } diff --git a/src/renderer/components/cluster-manager/clusters-menu.tsx b/src/renderer/components/cluster-manager/clusters-menu.tsx index f3b390a198..7f11cf395f 100644 --- a/src/renderer/components/cluster-manager/clusters-menu.tsx +++ b/src/renderer/components/cluster-manager/clusters-menu.tsx @@ -1,7 +1,7 @@ -import "./clusters-menu.scss" +import "./clusters-menu.scss"; import React from "react"; -import { remote } from "electron" +import { remote } from "electron"; import { requestMain } from "../../../common/ipc"; import type { Cluster } from "../../../main/cluster"; import { DragDropContext, Draggable, DraggableProvided, Droppable, DroppableProvided, DropResult } from "react-beautiful-dnd"; @@ -33,14 +33,14 @@ interface Props { export class ClustersMenu extends React.Component { showCluster = (clusterId: ClusterId) => { navigate(clusterViewURL({ params: { clusterId } })); - } + }; addCluster = () => { navigate(addClusterURL()); - } + }; showContextMenu = (cluster: Cluster) => { - const { Menu, MenuItem } = remote + const { Menu, MenuItem } = remote; const menu = new Menu(); menu.append(new MenuItem({ @@ -50,7 +50,7 @@ export class ClustersMenu extends React.Component { params: { clusterId: cluster.id } - })) + })); } })); if (cluster.online) { @@ -61,9 +61,9 @@ export class ClustersMenu extends React.Component { navigate(landingURL()); clusterStore.setActive(null); } - await requestMain(clusterDisconnectHandler, cluster.id) + await requestMain(clusterDisconnectHandler, cluster.id); } - })) + })); } menu.append(new MenuItem({ label: _i18n._(t`Remove`), @@ -81,13 +81,13 @@ export class ClustersMenu extends React.Component { clusterStore.removeById(cluster.id); }, message:

Are you sure want to remove cluster {cluster.contextName}?

, - }) + }); } })); menu.popup({ window: remote.getCurrentWindow() - }) - } + }); + }; @autobind() swapClusterIconOrder(result: DropResult) { @@ -96,17 +96,17 @@ export class ClustersMenu extends React.Component { const { source: { index: from }, destination: { index: to }, - } = result - clusterStore.swapIconOrders(currentWorkspaceId, from, to) + } = result; + clusterStore.swapIconOrders(currentWorkspaceId, from, to); } } render() { - const { className } = this.props - const { newContexts } = userStore - const workspace = workspaceStore.getById(workspaceStore.currentWorkspaceId) - const clusters = clusterStore.getByWorkspaceId(workspace.id) - const activeClusterId = clusterStore.activeCluster + const { className } = this.props; + const { newContexts } = userStore; + const workspace = workspaceStore.getById(workspaceStore.currentWorkspaceId); + const clusters = clusterStore.getByWorkspaceId(workspace.id); + const activeClusterId = clusterStore.activeCluster; return (
@@ -131,7 +131,7 @@ export class ClustersMenu extends React.Component {
)} - ) + ); })} {placeholder}
@@ -162,7 +162,7 @@ export class ClustersMenu extends React.Component { active={isActive} onClick={() => navigate(pageUrl)} /> - ) + ); })} diff --git a/src/renderer/components/cluster-manager/index.tsx b/src/renderer/components/cluster-manager/index.tsx index 92f878ad67..692f1676ef 100644 --- a/src/renderer/components/cluster-manager/index.tsx +++ b/src/renderer/components/cluster-manager/index.tsx @@ -1 +1 @@ -export * from "./cluster-manager" +export * from "./cluster-manager"; diff --git a/src/renderer/components/cluster-manager/lens-views.ts b/src/renderer/components/cluster-manager/lens-views.ts index 48c3578a0e..f10175ca02 100644 --- a/src/renderer/components/cluster-manager/lens-views.ts +++ b/src/renderer/components/cluster-manager/lens-views.ts @@ -23,13 +23,13 @@ export async function initView(clusterId: ClusterId) { if (!cluster) { return; } - logger.info(`[LENS-VIEW]: init dashboard, clusterId=${clusterId}`) + logger.info(`[LENS-VIEW]: init dashboard, clusterId=${clusterId}`); const parentElem = document.getElementById("lens-views"); const iframe = document.createElement("iframe"); iframe.name = cluster.contextName; - iframe.setAttribute("src", getClusterFrameUrl(clusterId)) + iframe.setAttribute("src", getClusterFrameUrl(clusterId)); iframe.addEventListener("load", () => { - logger.info(`[LENS-VIEW]: loaded from ${iframe.src}`) + logger.info(`[LENS-VIEW]: loaded from ${iframe.src}`); lensViews.get(clusterId).isLoaded = true; }, { once: true }); lensViews.set(clusterId, { clusterId, view: iframe }); @@ -39,15 +39,15 @@ export async function initView(clusterId: ClusterId) { export async function autoCleanOnRemove(clusterId: ClusterId, iframe: HTMLIFrameElement) { await when(() => !clusterStore.getById(clusterId)); - logger.info(`[LENS-VIEW]: remove dashboard, clusterId=${clusterId}`) - lensViews.delete(clusterId) + logger.info(`[LENS-VIEW]: remove dashboard, clusterId=${clusterId}`); + lensViews.delete(clusterId); // Keep frame in DOM to avoid possible bugs when same cluster re-created after being removed. // In that case for some reasons `webFrame.routingId` returns some previous frameId (usage in app.tsx) // Issue: https://github.com/lensapp/lens/issues/811 - iframe.dataset.meta = `${iframe.name} was removed at ${new Date().toLocaleString()}` - iframe.removeAttribute("name") - iframe.contentWindow.postMessage("teardown", "*") + iframe.dataset.meta = `${iframe.name} was removed at ${new Date().toLocaleString()}`; + iframe.removeAttribute("name"); + iframe.contentWindow.postMessage("teardown", "*"); } export function refreshViews() { @@ -56,6 +56,6 @@ export function refreshViews() { const isCurrent = clusterId === cluster?.id; const isReady = cluster?.available && cluster?.ready; const isVisible = isCurrent && isLoaded && isReady; - view.style.display = isVisible ? "flex" : "none" - }) + view.style.display = isVisible ? "flex" : "none"; + }); } diff --git a/src/renderer/components/confirm-dialog/confirm-dialog.tsx b/src/renderer/components/confirm-dialog/confirm-dialog.tsx index bb8be378e7..491ba99012 100644 --- a/src/renderer/components/confirm-dialog/confirm-dialog.tsx +++ b/src/renderer/components/confirm-dialog/confirm-dialog.tsx @@ -57,15 +57,15 @@ export class ConfirmDialog extends React.Component { this.isSaving = false; } this.close(); - } + }; onClose = () => { this.isSaving = false; - } + }; close = () => { ConfirmDialog.close(); - } + }; render() { const { className, ...dialogProps } = this.props; @@ -103,6 +103,6 @@ export class ConfirmDialog extends React.Component { /> - ) + ); } } diff --git a/src/renderer/components/confirm-dialog/index.ts b/src/renderer/components/confirm-dialog/index.ts index de21b827c1..2c2bf03c63 100644 --- a/src/renderer/components/confirm-dialog/index.ts +++ b/src/renderer/components/confirm-dialog/index.ts @@ -1 +1 @@ -export * from './confirm-dialog' \ No newline at end of file +export * from './confirm-dialog'; \ No newline at end of file diff --git a/src/renderer/components/dialog/dialog.tsx b/src/renderer/components/dialog/dialog.tsx index 5a4ce48f4e..7b08ab6e5d 100644 --- a/src/renderer/components/dialog/dialog.tsx +++ b/src/renderer/components/dialog/dialog.tsx @@ -42,11 +42,11 @@ export class Dialog extends React.PureComponent { }; @disposeOnUnmount - closeOnNavigate = reaction(() => navigation.getPath(), () => this.close()) + closeOnNavigate = reaction(() => navigation.getPath(), () => this.close()); public state: DialogState = { isOpen: this.props.isOpen, - } + }; get elem() { return findDOMNode(this) as HTMLElement; @@ -95,7 +95,7 @@ export class Dialog extends React.PureComponent { // Using document.body target to handle keydown event before Drawer does document.body.addEventListener('keydown', this.onEscapeKey); } - } + }; onClose = () => { this.props.onClose(); @@ -103,7 +103,7 @@ export class Dialog extends React.PureComponent { if (this.elem) this.elem.removeEventListener('click', this.onClickOutside); document.body.removeEventListener('keydown', this.onEscapeKey); } - } + }; onEscapeKey = (evt: KeyboardEvent) => { const escapeKey = evt.code === "Escape"; @@ -111,7 +111,7 @@ export class Dialog extends React.PureComponent { this.close(); evt.stopPropagation(); } - } + }; onClickOutside = (evt: MouseEvent) => { const target = evt.target as HTMLElement; @@ -119,7 +119,7 @@ export class Dialog extends React.PureComponent { this.close(); evt.stopPropagation(); } - } + }; render() { const { modal, animated, pinned } = this.props; diff --git a/src/renderer/components/dialog/index.ts b/src/renderer/components/dialog/index.ts index 20033cb0d2..20da8e550a 100644 --- a/src/renderer/components/dialog/index.ts +++ b/src/renderer/components/dialog/index.ts @@ -1 +1 @@ -export * from './dialog' +export * from './dialog'; diff --git a/src/renderer/components/dialog/logs-dialog.tsx b/src/renderer/components/dialog/logs-dialog.tsx index 4ce1b3b27f..cfb7aecbe5 100644 --- a/src/renderer/components/dialog/logs-dialog.tsx +++ b/src/renderer/components/dialog/logs-dialog.tsx @@ -22,13 +22,13 @@ export class LogsDialog extends React.Component { copyToClipboard = () => { if (copyToClipboard(this.logsElem)) { - Notifications.ok(_i18n._(t`Logs copied to clipboard.`)) + Notifications.ok(_i18n._(t`Logs copied to clipboard.`)); } - } + }; render() { const { title, logs, ...dialogProps } = this.props; - const header =
{title}
+ const header =
{title}
; const customButtons = (
- ) + ); return ( @@ -49,6 +49,6 @@ export class LogsDialog extends React.Component { - ) + ); } } diff --git a/src/renderer/components/dock/create-resource.tsx b/src/renderer/components/dock/create-resource.tsx index e665c831a0..8fa20cad3e 100644 --- a/src/renderer/components/dock/create-resource.tsx +++ b/src/renderer/components/dock/create-resource.tsx @@ -1,7 +1,7 @@ import "./create-resource.scss"; import React from "react"; -import jsYaml from "js-yaml" +import jsYaml from "js-yaml"; import { observable } from "mobx"; import { observer } from "mobx-react"; import { Plural, t, Trans } from "@lingui/macro"; @@ -22,7 +22,7 @@ interface Props { @observer export class CreateResource extends React.Component { - @observable error = "" + @observable error = ""; get tabId() { return this.props.tab.id; @@ -35,20 +35,20 @@ export class CreateResource extends React.Component { onChange = (value: string, error?: string) => { createResourceStore.setData(this.tabId, value); this.error = error; - } + }; create = async () => { if (this.error) return; if (!this.data.trim()) return; // do not save when field is empty const resources = jsYaml.safeLoadAll(this.data) - .filter(v => !!v) // skip empty documents if "---" pasted at the beginning or end + .filter(v => !!v); // skip empty documents if "---" pasted at the beginning or end const createdResources: string[] = []; const errors: string[] = []; await Promise.all( resources.map(data => { return resourceApplierApi.update(data) .then(item => createdResources.push(item.getName())) - .catch((err: JsonApiErrorParsed) => errors.push(err.toString())) + .catch((err: JsonApiErrorParsed) => errors.push(err.toString())); }) ); if (errors.length) { @@ -60,10 +60,10 @@ export class CreateResource extends React.Component { {" "} {createdResources.join(", ")} successfully created

- ) - Notifications.ok(successMessage) - return successMessage - } + ); + Notifications.ok(successMessage); + return successMessage; + }; render() { const { tabId, data, error, create, onChange } = this; @@ -83,6 +83,6 @@ export class CreateResource extends React.Component { onChange={onChange} /> - ) + ); } } diff --git a/src/renderer/components/dock/dock-tab.store.ts b/src/renderer/components/dock/dock-tab.store.ts index d644b628b7..519745f0f1 100644 --- a/src/renderer/components/dock/dock-tab.store.ts +++ b/src/renderer/components/dock/dock-tab.store.ts @@ -28,16 +28,16 @@ export class DockTabStore { if (!currentTabs.includes(tabId)) { this.clearData(tabId); } - }) + }); }); } protected serializeData() { const { storageSerializer } = this.options; return Array.from(this.data).map(([tabId, tabData]) => { - if (storageSerializer) return [tabId, storageSerializer(tabData)] + if (storageSerializer) return [tabId, storageSerializer(tabData)]; return [tabId, tabData]; - }) + }); } getData(tabId: TabId) { diff --git a/src/renderer/components/dock/dock-tab.tsx b/src/renderer/components/dock/dock-tab.tsx index 41c595432c..ba73e42d92 100644 --- a/src/renderer/components/dock/dock-tab.tsx +++ b/src/renderer/components/dock/dock-tab.tsx @@ -1,6 +1,6 @@ -import "./dock-tab.scss" +import "./dock-tab.scss"; -import React from "react" +import React from "react"; import { observer } from "mobx-react"; import { t } from "@lingui/macro"; import { autobind, cssNames, prevDefault } from "../../utils"; @@ -39,13 +39,13 @@ export class DockTab extends React.Component { /> )} - ) + ); return ( - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/dock/dock.store.ts b/src/renderer/components/dock/dock.store.ts index 2ec01df8de..07b37ef9cf 100644 --- a/src/renderer/components/dock/dock.store.ts +++ b/src/renderer/components/dock/dock.store.ts @@ -1,7 +1,7 @@ import MD5 from "crypto-js/md5"; import { action, computed, IReactionOptions, observable, reaction } from "mobx"; import { autobind, createStorage } from "../../utils"; -import throttle from "lodash/throttle" +import throttle from "lodash/throttle"; export type TabId = string; @@ -46,12 +46,12 @@ export class DockStore { } get maxHeight() { - const mainLayoutHeader = 40 - const mainLayoutTabs = 33 - const mainLayoutMargin = 16 - const dockTabs = 33 - const preferedMax = window.innerHeight - mainLayoutHeader - mainLayoutTabs - mainLayoutMargin - dockTabs - return Math.max(preferedMax, this.minHeight) // don't let max < min + const mainLayoutHeader = 40; + const mainLayoutTabs = 33; + const mainLayoutMargin = 16; + const dockTabs = 33; + const preferedMax = window.innerHeight - mainLayoutHeader - mainLayoutTabs - mainLayoutMargin - dockTabs; + return Math.max(preferedMax, this.minHeight); // don't let max < min } constructor() { @@ -138,7 +138,7 @@ export class DockStore { const tab: IDockTab = { id: tabId, ...anonTab }; if (addNumber) { const tabNumber = this.getNewTabNumber(tab.kind); - if (tabNumber > 1) tab.title += ` (${tabNumber})` + if (tabNumber > 1) tab.title += ` (${tabNumber})`; } this.tabs.push(tab); this.selectTab(tab.id); diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index f4936417e6..112a02b09b 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -42,27 +42,27 @@ export class Dock extends React.Component { if (selectedTab.pinned) close(); else closeTab(selectedTab.id); } - } + }; onChangeTab = (tab: IDockTab) => { const { open, selectTab } = dockStore; open(); selectTab(tab.id); - } + }; @autobind() renderTab(tab: IDockTab) { if (isTerminalTab(tab)) { - return + return ; } if (isCreateResourceTab(tab) || isEditResourceTab(tab)) { - return + return ; } if (isInstallChartTab(tab) || isUpgradeChartTab(tab)) { - return } /> + return } />; } if (isPodLogsTab(tab)) { - return + return ; } } @@ -78,7 +78,7 @@ export class Dock extends React.Component { {isTerminalTab(tab) && } {isPodLogsTab(tab) && } - ) + ); } render() { @@ -139,6 +139,6 @@ export class Dock extends React.Component { {this.renderTabContent()} - ) + ); } } diff --git a/src/renderer/components/dock/edit-resource.store.ts b/src/renderer/components/dock/edit-resource.store.ts index d01d604d37..8ae0dee2c5 100644 --- a/src/renderer/components/dock/edit-resource.store.ts +++ b/src/renderer/components/dock/edit-resource.store.ts @@ -42,7 +42,7 @@ export class EditResourceStore extends DockTabStore { }, { delay: 100 // make sure all stores initialized })); - }) + }); }); } @@ -58,7 +58,7 @@ export class EditResourceStore extends DockTabStore { Array.from(this.watchers).forEach(([tabId, dispose]) => { this.watchers.delete(tabId); dispose(); - }) + }); } } diff --git a/src/renderer/components/dock/edit-resource.tsx b/src/renderer/components/dock/edit-resource.tsx index 6d9aa961c2..471a6aa75c 100644 --- a/src/renderer/components/dock/edit-resource.tsx +++ b/src/renderer/components/dock/edit-resource.tsx @@ -3,7 +3,7 @@ import "./edit-resource.scss"; import React from "react"; import { autorun, observable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import jsYaml from "js-yaml" +import jsYaml from "js-yaml"; import { t, Trans } from "@lingui/macro"; import { IDockTab } from "./dock.store"; import { cssNames } from "../../utils"; @@ -62,7 +62,7 @@ export class EditResource extends React.Component { onChange = (draft: string, error?: string) => { this.error = error; this.saveDraft(draft); - } + }; save = async () => { if (this.error) { @@ -79,7 +79,7 @@ export class EditResource extends React.Component { {resourceType} {resourceName} updated.

); - } + }; render() { const { tabId, resource, tabData, error, onChange, save } = this; @@ -110,6 +110,6 @@ export class EditResource extends React.Component { onChange={onChange} /> - ) + ); } } diff --git a/src/renderer/components/dock/editor-panel.tsx b/src/renderer/components/dock/editor-panel.tsx index c52630a89d..8dee3ffa96 100644 --- a/src/renderer/components/dock/editor-panel.tsx +++ b/src/renderer/components/dock/editor-panel.tsx @@ -1,5 +1,5 @@ import React from "react"; -import jsYaml from "js-yaml" +import jsYaml from "js-yaml"; import { observable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { cssNames } from "../../utils"; @@ -21,7 +21,7 @@ export class EditorPanel extends React.Component { public editor: AceEditor; - @observable yamlError = "" + @observable yamlError = ""; componentDidMount() { // validate and run callback with optional error @@ -30,7 +30,7 @@ export class EditorPanel extends React.Component { disposeOnUnmount(this, [ dockStore.onTabChange(this.onTabChange, { delay: 250 }), dockStore.onResize(this.onResize, { delay: 250 }), - ]) + ]); } validate(value: string) { @@ -44,23 +44,23 @@ export class EditorPanel extends React.Component { onTabChange = () => { this.editor.focus(); - } + }; onResize = () => { this.editor.resize(); this.editor.focus(); - } + }; onCursorPosChange = (pos: Ace.Point) => { EditorPanel.cursorPos.setData(this.props.tabId, pos); - } + }; onChange = (value: string) => { this.validate(value); if (this.props.onChange) { this.props.onChange(value, this.yamlError); } - } + }; render() { const { value, tabId } = this.props; @@ -77,6 +77,6 @@ export class EditorPanel extends React.Component { onCursorPosChange={this.onCursorPosChange} ref={e => this.editor = e} /> - ) + ); } } diff --git a/src/renderer/components/dock/index.ts b/src/renderer/components/dock/index.ts index 08cc7287b9..c51aa2a3cd 100644 --- a/src/renderer/components/dock/index.ts +++ b/src/renderer/components/dock/index.ts @@ -1 +1 @@ -export * from "./dock" +export * from "./dock"; diff --git a/src/renderer/components/dock/info-panel.tsx b/src/renderer/components/dock/info-panel.tsx index 777aa01027..0404cc5981 100644 --- a/src/renderer/components/dock/info-panel.tsx +++ b/src/renderer/components/dock/info-panel.tsx @@ -38,7 +38,7 @@ export class InfoPanel extends Component { showSubmitClose: true, showInlineInfo: true, showNotifications: true, - } + }; @observable error = ""; @observable waiting = false; @@ -46,9 +46,9 @@ export class InfoPanel extends Component { componentDidMount() { disposeOnUnmount(this, [ reaction(() => this.props.tabId, () => { - this.waiting = false + this.waiting = false; }) - ]) + ]); } @computed get errorInfo() { @@ -64,18 +64,18 @@ export class InfoPanel extends Component { } catch (error) { if (showNotifications) Notifications.error(error.toString()); } finally { - this.waiting = false + this.waiting = false; } - } + }; submitAndClose = async () => { await this.submit(); this.close(); - } + }; close = () => { dockStore.closeTab(this.props.tabId); - } + }; renderErrorIcon() { if (!this.props.showInlineInfo || !this.errorInfo) { diff --git a/src/renderer/components/dock/install-chart.store.ts b/src/renderer/components/dock/install-chart.store.ts index bc31c44cb0..68c129f12a 100644 --- a/src/renderer/components/dock/install-chart.store.ts +++ b/src/renderer/components/dock/install-chart.store.ts @@ -30,24 +30,24 @@ export class InstallChartStore extends DockTabStore { const { selectedTab, isOpen } = dockStore; if (isInstallChartTab(selectedTab) && isOpen) { this.loadData() - .catch(err => Notifications.error(String(err))) + .catch(err => Notifications.error(String(err))); } - }, { delay: 250 }) + }, { delay: 250 }); } @action async loadData(tabId = dockStore.selectedTabId) { - const promises = [] + const promises = []; if (!this.getData(tabId).values) { - promises.push(this.loadValues(tabId)) + promises.push(this.loadValues(tabId)); } if (!this.versions.getData(tabId)) { - promises.push(this.loadVersions(tabId)) + promises.push(this.loadVersions(tabId)); } - await Promise.all(promises) + await Promise.all(promises); } @action @@ -61,15 +61,15 @@ export class InstallChartStore extends DockTabStore { @action async loadValues(tabId: TabId) { - const data = this.getData(tabId) - const { repo, name, version } = data + const data = this.getData(tabId); + const { repo, name, version } = data; // This loop is for "retrying" the "getValues" call for (const _ of Array(3)) { - const values = await helmChartsApi.getValues(repo, name, version) + const values = await helmChartsApi.getValues(repo, name, version); if (values) { - this.setData(tabId, { ...data, values }) - return + this.setData(tabId, { ...data, values }); + return; } } } diff --git a/src/renderer/components/dock/install-chart.tsx b/src/renderer/components/dock/install-chart.tsx index 56ee304dd6..0c0713007d 100644 --- a/src/renderer/components/dock/install-chart.tsx +++ b/src/renderer/components/dock/install-chart.tsx @@ -103,7 +103,7 @@ export class InstallChart extends Component { return (

Chart Release {details.release.name} successfully created.

); - } + }; render() { const { tabId, chartData, values, versions, install } = this; @@ -137,7 +137,7 @@ export class InstallChart extends Component { logs={this.releaseDetails.log} /> - ) + ); } const { repo, name, version, namespace, releaseName } = chartData; diff --git a/src/renderer/components/dock/pod-log-controls.tsx b/src/renderer/components/dock/pod-log-controls.tsx index bf247077af..469264210d 100644 --- a/src/renderer/components/dock/pod-log-controls.tsx +++ b/src/renderer/components/dock/pod-log-controls.tsx @@ -30,17 +30,17 @@ export const PodLogControls = observer((props: Props) => { const toggleTimestamps = () => { save({ showTimestamps: !showTimestamps }); - } + }; const togglePrevious = () => { save({ previous: !previous }); reload(); - } + }; const downloadLogs = () => { const fileName = selectedContainer ? selectedContainer.name : pod.getName(); downloadFile(fileName + ".log", logs.join("\n"), "text/plain"); - } + }; const onContainerChange = (option: SelectOption) => { const { containers, initContainers } = tabData; @@ -48,9 +48,9 @@ export const PodLogControls = observer((props: Props) => { selectedContainer: containers .concat(initContainers) .find(container => container.name === option.value) - }) + }); reload(); - } + }; const containerSelectOptions = () => { const { containers, initContainers } = tabData; @@ -58,22 +58,22 @@ export const PodLogControls = observer((props: Props) => { { label: _i18n._(t`Containers`), options: containers.map(container => { - return { value: container.name } + return { value: container.name }; }), }, { label: _i18n._(t`Init Containers`), options: initContainers.map(container => { - return { value: container.name } + return { value: container.name }; }), } ]; - } + }; const formatOptionLabel = (option: SelectOption) => { const { value, label } = option; return label || <> {value}; - } + }; return (
diff --git a/src/renderer/components/dock/pod-log-search.tsx b/src/renderer/components/dock/pod-log-search.tsx index 7dd83eef3d..296022a40f 100644 --- a/src/renderer/components/dock/pod-log-search.tsx +++ b/src/renderer/components/dock/pod-log-search.tsx @@ -33,22 +33,22 @@ export const PodLogSearch = observer((props: PodLogSearchProps) => { const onPrevOverlay = () => { setPrevOverlayActive(); toPrevOverlay(); - } + }; const onNextOverlay = () => { setNextOverlayActive(); toNextOverlay(); - } + }; const onClear = () => { setSearch(""); - } + }; const onKeyDown = (evt: React.KeyboardEvent) => { if (evt.key === "Enter") { onNextOverlay(); } - } + }; useEffect(() => { // Refresh search when logs changed diff --git a/src/renderer/components/dock/pod-logs.store.ts b/src/renderer/components/dock/pod-logs.store.ts index 35cbe6a90f..6d2fae1545 100644 --- a/src/renderer/components/dock/pod-logs.store.ts +++ b/src/renderer/components/dock/pod-logs.store.ts @@ -25,9 +25,9 @@ export const logRange = 500; @autobind() export class PodLogsStore extends DockTabStore { private refresher = interval(10, () => { - const id = dockStore.selectedTabId - if (!this.logs.get(id)) return - this.loadMore(id) + const id = dockStore.selectedTabId; + if (!this.logs.get(id)) return; + this.loadMore(id); }); @observable logs = observable.map(); @@ -48,12 +48,12 @@ export class PodLogsStore extends DockTabStore { reaction(() => this.logs.get(dockStore.selectedTabId), () => { this.setNewLogSince(dockStore.selectedTabId); - }) + }); reaction(() => dockStore.selectedTabId, () => { // Clear search query on tab change searchStore.reset(); - }) + }); } /** @@ -78,7 +78,7 @@ export class PodLogsStore extends DockTabStore { this.refresher.stop(); this.logs.set(tabId, message); } - } + }; /** * Function is used to refreser/stream-like requests. @@ -94,7 +94,7 @@ export class PodLogsStore extends DockTabStore { }); // Add newly received logs to bottom this.logs.set(tabId, [...oldLogs, ...logs]); - } + }; /** * Main logs loading function adds necessary data to payload and makes @@ -119,7 +119,7 @@ export class PodLogsStore extends DockTabStore { logs.pop(); // Remove last empty element return logs; }); - } + }; /** * Sets newLogSince separator timestamp to split old logs from new ones diff --git a/src/renderer/components/dock/pod-logs.tsx b/src/renderer/components/dock/pod-logs.tsx index 9985a0d913..1e7d7e4a14 100644 --- a/src/renderer/components/dock/pod-logs.tsx +++ b/src/renderer/components/dock/pod-logs.tsx @@ -1,7 +1,7 @@ import "./pod-logs.scss"; import React from "react"; import AnsiUp from 'ansi_up'; -import DOMPurify from "dompurify" +import DOMPurify from "dompurify"; import { Trans } from "@lingui/macro"; import { action, computed, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; @@ -79,13 +79,13 @@ export class PodLogs extends React.Component { this.ready = false; await podLogsStore.load(this.tabId); this.ready = true; - } + }; reload = async () => { podLogsStore.clearLogs(this.tabId); this.lastLineIsShown = true; await this.load(); - } + }; /** * Function loads more logs (usually after user scrolls to top) and sets proper @@ -101,7 +101,7 @@ export class PodLogs extends React.Component { // Set scroll position back to place where preloading started this.logsElement.current.scrollTop = (podLogsStore.lines - lines) * lineHeight; } - } + }; /** * A function for various actions after search is happened @@ -167,7 +167,7 @@ export class PodLogs extends React.Component { this.showJumpToBottom = true; } } - } + }; @action scrollToBottom = () => { @@ -177,7 +177,7 @@ export class PodLogs extends React.Component { this.showJumpToBottom = false; // Showing horizontal scrollbar after VirtualList settles down setTimeout(() => this.hideHorizontalScroll = false, 500); - } + }; /** * A function is called by VirtualList for rendering each of the row @@ -205,14 +205,14 @@ export class PodLogs extends React.Component { className={cssNames("overlay", { active })} dangerouslySetInnerHTML={{ __html: ansiToHtml(overlayValue) }} /> : - null + null; contents.push( {overlay} ); - }) + }); } return (
@@ -221,7 +221,7 @@ export class PodLogs extends React.Component { )}
); - } + }; renderJumpToBottom() { if (!this.logsElement) return null; @@ -288,7 +288,7 @@ export class PodLogs extends React.Component { toPrevOverlay={this.toOverlay} toNextOverlay={this.toOverlay} /> - ) + ); return (
{ componentDidMount() { reaction(() => this.isDisconnected === true, () => { - dockStore.closeTab(this.tabId) - }) + dockStore.closeTab(this.tabId); + }); } get tabId() { @@ -55,6 +55,6 @@ export class TerminalTab extends React.Component { /> )} /> - ) + ); } } diff --git a/src/renderer/components/dock/terminal-window.tsx b/src/renderer/components/dock/terminal-window.tsx index 736b400e77..fab2c950ee 100644 --- a/src/renderer/components/dock/terminal-window.tsx +++ b/src/renderer/components/dock/terminal-window.tsx @@ -24,7 +24,7 @@ export class TerminalWindow extends React.Component { reaction(() => this.props.tab.id, tabId => this.activate(tabId), { fireImmediately: true }) - ]) + ]); } activate(tabId = this.props.tab.id) { @@ -40,6 +40,6 @@ export class TerminalWindow extends React.Component { className={cssNames("TerminalWindow", className, themeStore.activeTheme.type)} ref={e => this.elem = e} /> - ) + ); } } diff --git a/src/renderer/components/dock/terminal.ts b/src/renderer/components/dock/terminal.ts index ea17554a31..d0009f3c8b 100644 --- a/src/renderer/components/dock/terminal.ts +++ b/src/renderer/components/dock/terminal.ts @@ -15,7 +15,7 @@ export class Terminal { // https://xtermjs.org/docs/api/terminal/classes/terminal/#open const pool = document.createElement("div"); pool.className = "terminal-init"; - pool.style.cssText = "position: absolute; top: 0; left: 0; height: 0; visibility: hidden; overflow: hidden" + pool.style.cssText = "position: absolute; top: 0; left: 0; height: 0; visibility: hidden; overflow: hidden"; document.body.appendChild(pool); Terminal.spawningPool = pool; } @@ -36,7 +36,7 @@ export class Terminal { protected setTheme(colors: Record) { // Replacing keys stored in styles to format accepted by terminal // E.g. terminalBrightBlack -> brightBlack - const colorPrefix = "terminal" + const colorPrefix = "terminal"; const terminalColors = Object.entries(colors) .filter(([name]) => name.startsWith(colorPrefix)) .reduce((colors, [name, color]) => { @@ -132,39 +132,39 @@ export class Terminal { focus = () => { this.xterm.focus(); - } + }; onApiData = (data: string) => { this.xterm.write(data); - } + }; onData = (data: string) => { if (!this.api.isReady) return; this.api.sendCommand(data); - } + }; onScroll = () => { this.scrollPos = this.viewport.scrollTop; - } + }; onClear = () => { this.xterm.clear(); - } + }; onResize = () => { this.fitLazy(); this.focus(); - } + }; onActivate = () => { this.fit(); setTimeout(() => this.focus(), 250); // delay used to prevent focus on active tab this.viewport.scrollTop = this.scrollPos; // restore last scroll position - } + }; onClickLink = (evt: MouseEvent, link: string) => { window.open(link, "_blank"); - } + }; keyHandler = (evt: KeyboardEvent): boolean => { const { code, ctrlKey, type } = evt; @@ -190,7 +190,7 @@ export class Terminal { } return true; - } + }; } Terminal.init(); diff --git a/src/renderer/components/dock/upgrade-chart.store.ts b/src/renderer/components/dock/upgrade-chart.store.ts index 035929bc5c..55574aa0a7 100644 --- a/src/renderer/components/dock/upgrade-chart.store.ts +++ b/src/renderer/components/dock/upgrade-chart.store.ts @@ -90,7 +90,7 @@ export class UpgradeChartStore extends DockTabStore { const item = [...this.data].find(item => item[1].releaseName === releaseName); if (item) { const [tabId] = item; - return dockStore.getTabById(tabId) + return dockStore.getTabById(tabId); } } } @@ -113,7 +113,7 @@ export function createUpgradeChartTab(release: HelmRelease, tabParams: Partial { onChange = (value: string, error?: string) => { upgradeChartStore.values.setData(this.tabId, value); this.error = error; - } + }; upgrade = async () => { if (this.error) return; const { version, repo } = this.version; const releaseName = this.release.getName(); - const releaseNs = this.release.getNs() + const releaseNs = this.release.getNs(); await releaseStore.update(releaseName, releaseNs, { chart: this.release.getChart(), values: this.value, @@ -78,14 +78,14 @@ export class UpgradeChart extends React.Component {

Release {releaseName} successfully upgraded to version {version}

- ) - } + ); + }; formatVersionLabel = ({ value }: SelectOption) => { const chartName = this.release.getChart(); const { repo, version } = value; return `${repo}/${chartName}-${version}`; - } + }; render() { const { tabId, release, value, error, onChange, upgrade, versions, version } = this; @@ -110,7 +110,7 @@ export class UpgradeChart extends React.Component { onChange={({ value }: SelectOption) => this.version = value} />
- ) + ); return (
{ onChange={onChange} />
- ) + ); } } diff --git a/src/renderer/components/drawer/drawer-item-labels.tsx b/src/renderer/components/drawer/drawer-item-labels.tsx index a3f33a27f3..9964259da1 100644 --- a/src/renderer/components/drawer/drawer-item-labels.tsx +++ b/src/renderer/components/drawer/drawer-item-labels.tsx @@ -15,5 +15,5 @@ export function DrawerItemLabels(props: DrawerItemLabelsProps) { {labels.map(label => )} - ) + ); } diff --git a/src/renderer/components/drawer/drawer-item.tsx b/src/renderer/components/drawer/drawer-item.tsx index e50619fe5d..6a0e1874cb 100644 --- a/src/renderer/components/drawer/drawer-item.tsx +++ b/src/renderer/components/drawer/drawer-item.tsx @@ -13,17 +13,17 @@ export interface DrawerItemProps extends React.HTMLAttributes { export class DrawerItem extends React.Component { render() { - const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props - if (hidden) return null + const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props; + if (hidden) return null; const classNames = cssNames("DrawerItem", className, { labelsOnly }); - const content = displayBooleans(renderBoolean, children) + const content = displayBooleans(renderBoolean, children); return (
{name} {content}
- ) + ); } } diff --git a/src/renderer/components/drawer/drawer-param-toggler.tsx b/src/renderer/components/drawer/drawer-param-toggler.tsx index c7935fc414..181965e848 100644 --- a/src/renderer/components/drawer/drawer-param-toggler.tsx +++ b/src/renderer/components/drawer/drawer-param-toggler.tsx @@ -13,17 +13,17 @@ interface State { open?: boolean; } export class DrawerParamToggler extends React.Component { - public state: State = {} + public state: State = {}; toggle = () => { - this.setState({ open: !this.state.open }) - } + this.setState({ open: !this.state.open }); + }; render() { - const { label, children } = this.props - const { open } = this.state - const icon = `arrow_drop_${open ? "up" : "down"}` - const link = open ? _i18n._(t`Hide`) : _i18n._(t`Show`) + const { label, children } = this.props; + const { open } = this.state; + const icon = `arrow_drop_${open ? "up" : "down"}`; + const link = open ? _i18n._(t`Hide`) : _i18n._(t`Show`); return (
@@ -35,6 +35,6 @@ export class DrawerParamToggler extends React.Component
{children}
- ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/drawer/drawer-title.tsx b/src/renderer/components/drawer/drawer-title.tsx index d368f1888d..7e521c183e 100644 --- a/src/renderer/components/drawer/drawer-title.tsx +++ b/src/renderer/components/drawer/drawer-title.tsx @@ -9,11 +9,11 @@ export interface DrawerTitleProps { export class DrawerTitle extends React.Component { render() { - const { title, children, className } = this.props + const { title, children, className } = this.props; return (
{title || children}
- ) + ); } } diff --git a/src/renderer/components/drawer/drawer.tsx b/src/renderer/components/drawer/drawer.tsx index d76e99f5c0..0c425c1624 100644 --- a/src/renderer/components/drawer/drawer.tsx +++ b/src/renderer/components/drawer/drawer.tsx @@ -30,9 +30,9 @@ const defaultProps: Partial = { export class Drawer extends React.Component { static defaultProps = defaultProps as object; - private mouseDownTarget: HTMLElement - private contentElem: HTMLElement - private scrollElem: HTMLElement + private mouseDownTarget: HTMLElement; + private contentElem: HTMLElement; + private scrollElem: HTMLElement; private scrollPos = new Map(); private stopListenLocation = history.listen(() => { @@ -41,29 +41,29 @@ export class Drawer extends React.Component { componentDidMount() { // Using window target for events to make sure they will be catched after other places (e.g. Dialog) - window.addEventListener("mousedown", this.onMouseDown) - window.addEventListener("click", this.onClickOutside) - window.addEventListener("keydown", this.onEscapeKey) + window.addEventListener("mousedown", this.onMouseDown); + window.addEventListener("click", this.onClickOutside); + window.addEventListener("keydown", this.onEscapeKey); } componentWillUnmount() { this.stopListenLocation(); - window.removeEventListener("mousedown", this.onMouseDown) - window.removeEventListener("click", this.onClickOutside) - window.removeEventListener("keydown", this.onEscapeKey) + window.removeEventListener("mousedown", this.onMouseDown); + window.removeEventListener("click", this.onClickOutside); + window.removeEventListener("keydown", this.onEscapeKey); } saveScrollPos = () => { if (!this.scrollElem) return; const key = history.location.key; this.scrollPos.set(key, this.scrollElem.scrollTop); - } + }; restoreScrollPos = () => { if (!this.scrollElem) return; const key = history.location.key; this.scrollElem.scrollTop = this.scrollPos.get(key) || 0; - } + }; onEscapeKey = (evt: KeyboardEvent) => { if (!this.props.open) { @@ -72,34 +72,34 @@ export class Drawer extends React.Component { if (evt.code === "Escape") { this.close(); } - } + }; onClickOutside = (evt: MouseEvent) => { - const { contentElem, mouseDownTarget, close, props: { open } } = this + const { contentElem, mouseDownTarget, close, props: { open } } = this; if (!open || evt.defaultPrevented || contentElem.contains(mouseDownTarget)) { return; } const clickedElem = evt.target as HTMLElement; const isOutsideAnyDrawer = !clickedElem.closest('.Drawer'); if (isOutsideAnyDrawer) { - close() + close(); } - this.mouseDownTarget = null - } + this.mouseDownTarget = null; + }; onMouseDown = (evt: MouseEvent) => { if (this.props.open) { - this.mouseDownTarget = evt.target as HTMLElement + this.mouseDownTarget = evt.target as HTMLElement; } - } + }; close = () => { - const { open, onClose } = this.props + const { open, onClose } = this.props; if (open) onClose(); - } + }; render() { - const { open, position, title, animation, children, toolbar, size, usePortal } = this.props + const { open, position, title, animation, children, toolbar, size, usePortal } = this.props; let { className, contentClass } = this.props; className = cssNames("Drawer", className, position); contentClass = cssNames("drawer-content flex column box grow", contentClass); @@ -119,7 +119,7 @@ export class Drawer extends React.Component {
- ) + ); return usePortal ? createPortal(drawer, document.body) : drawer; } } diff --git a/src/renderer/components/drawer/index.ts b/src/renderer/components/drawer/index.ts index c46b42cc6b..8bc907fd4b 100644 --- a/src/renderer/components/drawer/index.ts +++ b/src/renderer/components/drawer/index.ts @@ -1,5 +1,5 @@ -export * from "./drawer" -export * from "./drawer-title" -export * from "./drawer-item" -export * from "./drawer-item-labels" -export * from "./drawer-param-toggler" +export * from "./drawer"; +export * from "./drawer-title"; +export * from "./drawer-item"; +export * from "./drawer-item-labels"; +export * from "./drawer-param-toggler"; diff --git a/src/renderer/components/editable-list/editable-list.tsx b/src/renderer/components/editable-list/editable-list.tsx index 76b533b9b8..3e3613086c 100644 --- a/src/renderer/components/editable-list/editable-list.tsx +++ b/src/renderer/components/editable-list/editable-list.tsx @@ -1,4 +1,4 @@ -import "./editable-list.scss" +import "./editable-list.scss"; import React from "react"; import { Icon } from "../icon"; @@ -22,7 +22,7 @@ export interface Props { const defaultProps: Partial> = { placeholder: _i18n._("Add new item..."), renderItem: (item: any, index: number) => {item} -} +}; @observer export class EditableList extends React.Component> { @@ -31,11 +31,11 @@ export class EditableList extends React.Component> { @autobind() onSubmit(val: string) { - const { add } = this.props + const { add } = this.props; if (val) { - add(val) - this.currentNewItem = "" + add(val); + this.currentNewItem = ""; } } @@ -66,6 +66,6 @@ export class EditableList extends React.Component> { } - ) + ); } } diff --git a/src/renderer/components/editable-list/index.ts b/src/renderer/components/editable-list/index.ts index 3ca5ee970e..cc0293acd6 100644 --- a/src/renderer/components/editable-list/index.ts +++ b/src/renderer/components/editable-list/index.ts @@ -1 +1 @@ -export * from "./editable-list" \ No newline at end of file +export * from "./editable-list"; \ No newline at end of file diff --git a/src/renderer/components/error-boundary/error-boundary.tsx b/src/renderer/components/error-boundary/error-boundary.tsx index 7ce72c99c2..87a214ff67 100644 --- a/src/renderer/components/error-boundary/error-boundary.tsx +++ b/src/renderer/components/error-boundary/error-boundary.tsx @@ -1,4 +1,4 @@ -import "./error-boundary.scss" +import "./error-boundary.scss"; import React, { ErrorInfo } from "react"; import { reaction } from "mobx"; @@ -25,7 +25,7 @@ export class ErrorBoundary extends React.Component { resetOnNavigate = reaction( () => navigation.getPath(), () => this.setState({ error: null, errorInfo: null }) - ) + ); componentDidCatch(error: Error, errorInfo: ErrorInfo) { this.setState({ error, errorInfo }); @@ -33,13 +33,13 @@ export class ErrorBoundary extends React.Component { back = () => { navigation.goBack(); - } + }; render() { const { error, errorInfo } = this.state; if (error) { - const slackLink = Slack - const githubLink = Github + const slackLink = Slack; + const githubLink = Github; const pageUrl = location.href; return (
@@ -67,7 +67,7 @@ export class ErrorBoundary extends React.Component { onClick={this.back} />
- ) + ); } return this.props.children; } diff --git a/src/renderer/components/error-boundary/index.ts b/src/renderer/components/error-boundary/index.ts index 7b1daafe3c..cdcf838466 100644 --- a/src/renderer/components/error-boundary/index.ts +++ b/src/renderer/components/error-boundary/index.ts @@ -1 +1 @@ -export * from "./error-boundary" \ No newline at end of file +export * from "./error-boundary"; \ No newline at end of file diff --git a/src/renderer/components/file-picker/file-picker.tsx b/src/renderer/components/file-picker/file-picker.tsx index 5af7a176d1..1fcd26f766 100644 --- a/src/renderer/components/file-picker/file-picker.tsx +++ b/src/renderer/components/file-picker/file-picker.tsx @@ -1,4 +1,4 @@ -import "./file-picker.scss" +import "./file-picker.scss"; import React from "react"; import fse from "fs-extra"; @@ -125,7 +125,7 @@ export class FilePicker extends React.Component { switch (onOverTotalSizeLimit) { case OverTotalSizeLimitStyle.FILTER_LARGEST: - files = _.orderBy(files, ["size"]) + files = _.orderBy(files, ["size"]); case OverTotalSizeLimitStyle.FILTER_LAST: let newTotalSize = totalSize; @@ -193,11 +193,11 @@ export class FilePicker extends React.Component { getIconRight(): React.ReactNode { switch (this.status) { case FileInputStatus.CLEAR: - return + return ; case FileInputStatus.PROCESSING: return ; case FileInputStatus.ERROR: - return + return ; } } } \ No newline at end of file diff --git a/src/renderer/components/file-picker/index.ts b/src/renderer/components/file-picker/index.ts index 9e4bd291c2..f58aec1470 100644 --- a/src/renderer/components/file-picker/index.ts +++ b/src/renderer/components/file-picker/index.ts @@ -1 +1 @@ -export * from "./file-picker" \ No newline at end of file +export * from "./file-picker"; \ No newline at end of file diff --git a/src/renderer/components/icon/icon.tsx b/src/renderer/components/icon/icon.tsx index 8fc86e6301..8e99eb0095 100644 --- a/src/renderer/components/icon/icon.tsx +++ b/src/renderer/components/icon/icon.tsx @@ -1,4 +1,4 @@ -import './icon.scss' +import './icon.scss'; import React, { ReactNode } from "react"; import { findDOMNode } from "react-dom"; @@ -6,7 +6,7 @@ import { NavLink } from "react-router-dom"; import { LocationDescriptor } from 'history'; import { autobind, cssNames } from "../../utils"; import { TooltipDecoratorProps, withTooltip } from "../tooltip"; -import isNumber from "lodash/isNumber" +import isNumber from "lodash/isNumber"; export interface IconProps extends React.HTMLAttributes, TooltipDecoratorProps { material?: string; // material-icon, see available names at https://material.io/icons/ @@ -106,11 +106,11 @@ export class Icon extends React.PureComponent { // render icon type if (link) { - return + return ; } if (href) { - return + return ; } - return + return ; } } diff --git a/src/renderer/components/icon/index.ts b/src/renderer/components/icon/index.ts index 32ff10956e..5cdcefa69c 100644 --- a/src/renderer/components/icon/index.ts +++ b/src/renderer/components/icon/index.ts @@ -1 +1 @@ -export * from "./icon" \ No newline at end of file +export * from "./icon"; \ No newline at end of file diff --git a/src/renderer/components/input/file-input.tsx b/src/renderer/components/input/file-input.tsx index 0d0e467601..1293163797 100644 --- a/src/renderer/components/input/file-input.tsx +++ b/src/renderer/components/input/file-input.tsx @@ -24,7 +24,7 @@ export class FileInput extends React.Component { selectFiles = () => { this.input.click(); // opens system dialog for selecting files - } + }; protected onChange = async (evt: React.ChangeEvent) => { const fileList = Array.from(evt.target.files); @@ -41,15 +41,15 @@ export class FileInput extends React.Component { file: file, data: reader.result, error: reader.error ? String(reader.error) : null, - }) + }); }; reader.readAsText(file); - }) + }); }); selectedFiles = await Promise.all(readingFiles); } this.props.onSelectFiles(...selectedFiles); - } + }; render() { const { onSelectFiles, readAsText, ...props } = this.props; @@ -61,6 +61,6 @@ export class FileInput extends React.Component { ref={e => this.input = e} {...props} /> - ) + ); } } diff --git a/src/renderer/components/input/index.ts b/src/renderer/components/input/index.ts index b4bfe3a56b..fc930e45d2 100644 --- a/src/renderer/components/input/index.ts +++ b/src/renderer/components/input/index.ts @@ -1,4 +1,4 @@ -export * from './input' -export * from './search-input' -export * from './search-input-url' -export * from './file-input' +export * from './input'; +export * from './search-input'; +export * from './search-input-url'; +export * from './file-input'; diff --git a/src/renderer/components/input/input.tsx b/src/renderer/components/input/input.tsx index f0938255a6..e61ecc3020 100644 --- a/src/renderer/components/input/input.tsx +++ b/src/renderer/components/input/input.tsx @@ -5,13 +5,13 @@ import { autobind, cssNames, debouncePromise } from "../../utils"; import { Icon } from "../icon"; import * as Validators from "./input_validators"; import { InputValidator } from "./input_validators"; -import isString from "lodash/isString" -import isFunction from "lodash/isFunction" -import isBoolean from "lodash/isBoolean" -import uniqueId from "lodash/uniqueId" +import isString from "lodash/isString"; +import isFunction from "lodash/isFunction"; +import isBoolean from "lodash/isBoolean"; +import uniqueId from "lodash/uniqueId"; const { conditionalValidators, ...InputValidators } = Validators; -export { InputValidators, InputValidator } +export { InputValidators, InputValidator }; type InputElement = HTMLInputElement | HTMLTextAreaElement; type InputElementProps = InputHTMLAttributes & TextareaHTMLAttributes & DOMAttributes; @@ -31,7 +31,7 @@ export type InputProps = Omit): void; onSubmit?(value: T): void; -} +}; interface State { focused?: boolean; @@ -47,7 +47,7 @@ const defaultProps: Partial = { maxRows: 10000, showValidationLine: true, validators: [], -} +}; export class Input extends React.Component { static defaultProps = defaultProps as object; @@ -59,7 +59,7 @@ export class Input extends React.Component { dirty: !!this.props.dirty, valid: true, errors: [], - } + }; setValue(value: string) { if (value !== this.getValue()) { @@ -86,7 +86,7 @@ export class Input extends React.Component { } select() { - this.input.select() + this.input.select(); } private autoFitHeight() { @@ -154,7 +154,7 @@ export class Input extends React.Component { } private getValidatorError(value: string, { message }: InputValidator) { - if (isFunction(message)) return message(value, this.props) + if (isFunction(message)) return message(value, this.props); return message || ""; } diff --git a/src/renderer/components/input/input_validators.ts b/src/renderer/components/input/input_validators.ts index e94eafe0cd..708415b66c 100644 --- a/src/renderer/components/input/input_validators.ts +++ b/src/renderer/components/input/input_validators.ts @@ -32,7 +32,7 @@ export const isNumber: InputValidator = { isNaN(numVal) || (min != null && numVal < min) || (max != null && numVal > max) - ) + ); }, }; @@ -46,7 +46,7 @@ export const isPath: InputValidator = { condition: ({ type }) => type === "text", message: () => _i18n._(t`This field must be a valid path`), validate: value => !value || fse.pathExistsSync(value), -} +}; export const minLength: InputValidator = { condition: ({ minLength }) => !!minLength, diff --git a/src/renderer/components/input/search-input-url.tsx b/src/renderer/components/input/search-input-url.tsx index 87181d89c1..854adc1024 100644 --- a/src/renderer/components/input/search-input-url.tsx +++ b/src/renderer/components/input/search-input-url.tsx @@ -15,25 +15,25 @@ export class SearchInputUrl extends React.Component { @observable inputVal = ""; // fix: use empty string to avoid react warnings @disposeOnUnmount - updateInput = autorun(() => this.inputVal = getSearch()) - updateUrl = debounce((val: string) => setSearch(val), 250) + updateInput = autorun(() => this.inputVal = getSearch()); + updateUrl = debounce((val: string) => setSearch(val), 250); setValue = (value: string) => { this.inputVal = value; this.updateUrl(value); - } + }; clear = () => { this.setValue(""); this.updateUrl.flush(); - } + }; onChange = (val: string, evt: React.ChangeEvent) => { this.setValue(val); if (this.props.onChange) { this.props.onChange(val, evt); } - } + }; render() { const { inputVal } = this; @@ -44,6 +44,6 @@ export class SearchInputUrl extends React.Component { onClear={this.clear} {...this.props} /> - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/input/search-input.tsx b/src/renderer/components/input/search-input.tsx index a2caf748ca..9c9530030b 100644 --- a/src/renderer/components/input/search-input.tsx +++ b/src/renderer/components/input/search-input.tsx @@ -18,9 +18,9 @@ const defaultProps: Partial = { autoFocus: true, closeIcon: true, get placeholder() { - return _i18n._(t`Search...`) + return _i18n._(t`Search...`); }, -} +}; @observer export class SearchInput extends React.Component { @@ -40,11 +40,11 @@ export class SearchInput extends React.Component { if (this.props.onClear) { this.props.onClear(); } - } + }; onChange = (val: string, evt: React.ChangeEvent) => { this.props.onChange(val, evt); - } + }; onKeyDown = (evt: React.KeyboardEvent) => { if (this.props.onKeyDown) { @@ -56,7 +56,7 @@ export class SearchInput extends React.Component { this.clear(); evt.stopPropagation(); } - } + }; @autobind() focus(evt: KeyboardEvent) { @@ -70,7 +70,7 @@ export class SearchInput extends React.Component { const { className, compact, closeIcon, onClear, ...inputProps } = this.props; const icon = this.props.value ? closeIcon ? : null - : + : ; return ( { iconRight={icon} ref={this.input} /> - ) + ); } } diff --git a/src/renderer/components/item-object-list/filter-icon.tsx b/src/renderer/components/item-object-list/filter-icon.tsx index c9280a434d..801c9116be 100644 --- a/src/renderer/components/item-object-list/filter-icon.tsx +++ b/src/renderer/components/item-object-list/filter-icon.tsx @@ -1,4 +1,4 @@ -import React from "react" +import React from "react"; import { Icon, IconProps } from "../icon"; import { FilterType } from "./page-filters.store"; @@ -16,6 +16,6 @@ export function FilterIcon(props: Props) { return ; default: - return + return ; } } diff --git a/src/renderer/components/item-object-list/index.tsx b/src/renderer/components/item-object-list/index.tsx index f75ea77c55..b0b106b298 100644 --- a/src/renderer/components/item-object-list/index.tsx +++ b/src/renderer/components/item-object-list/index.tsx @@ -1 +1 @@ -export * from "./item-list-layout" \ No newline at end of file +export * from "./item-list-layout"; \ No newline at end of file diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index fa99b3405b..9fbcb54add 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -1,5 +1,5 @@ -import "./item-list-layout.scss" -import groupBy from "lodash/groupBy" +import "./item-list-layout.scss"; +import groupBy from "lodash/groupBy"; import React, { ReactNode } from "react"; import { computed, observable, reaction, toJS, when } from "mobx"; @@ -120,7 +120,7 @@ export class ItemListLayout extends React.Component { await when(() => this.isUnmounting); subscriptions.forEach(dispose => dispose()); // unsubscribe all } catch (error) { - console.log("catched", error) + console.log("catched", error); } } @@ -141,7 +141,7 @@ export class ItemListLayout extends React.Component { return searchFilters.some(getTexts => { const sourceTexts: string[] = [getTexts(item)].flat().map(normalizeText); return sourceTexts.some(source => searchTexts.some(search => source.includes(search))); - }) + }); }); } return items; @@ -150,11 +150,11 @@ export class ItemListLayout extends React.Component { [FilterType.NAMESPACE]: items => { const filterValues = pageFilters.getValues(FilterType.NAMESPACE); if (filterValues.length > 0) { - return items.filter(item => filterValues.includes(item.getNs())) + return items.filter(item => filterValues.includes(item.getNs())); } return items; }, - } + }; @computed get isReady() { const { isReady, store } = this.props; @@ -235,7 +235,7 @@ export class ItemListLayout extends React.Component { cellProps.className = cssNames(cellProps.className, headCell.className); } } - return + return ; }) } {renderItemMenu && ( @@ -268,7 +268,7 @@ export class ItemListLayout extends React.Component { /> ), ...dialogCustomProps, - }) + }); } renderFilters() { @@ -277,7 +277,7 @@ export class ItemListLayout extends React.Component { if (!isReady || !filters.length || hideFilters || !userSettings.showAppliedFilters) { return; } - return + return ; } renderNoItems() { @@ -295,9 +295,9 @@ export class ItemListLayout extends React.Component {

- ) + ); } - return + return ; } renderHeaderContent(placeholders: IHeaderPlaceholders): ReactNode { @@ -311,7 +311,7 @@ export class ItemListLayout extends React.Component { {filters} {search} - ) + ); } renderInfo() { @@ -325,7 +325,7 @@ export class ItemListLayout extends React.Component { Filtered: {itemsCount} / {allItemsCount} - ) + ); } return ( { }} /> , search: , - } + }; let header = this.renderHeaderContent(placeholders); if (customizeHeader) { const modifiedHeader = customizeHeader(placeholders, header); @@ -367,7 +367,7 @@ export class ItemListLayout extends React.Component {
{header}
- ) + ); } renderList() { @@ -421,7 +421,7 @@ export class ItemListLayout extends React.Component { {...addRemoveButtons} /> - ) + ); } renderFooter() { diff --git a/src/renderer/components/item-object-list/page-filters-list.tsx b/src/renderer/components/item-object-list/page-filters-list.tsx index 990f1bce3e..492dffe20a 100644 --- a/src/renderer/components/item-object-list/page-filters-list.tsx +++ b/src/renderer/components/item-object-list/page-filters-list.tsx @@ -1,5 +1,5 @@ -import "./page-filters-list.scss" -import React from "react" +import "./page-filters-list.scss"; +import React from "react"; import { observer } from "mobx-react"; import { Trans } from "@lingui/macro"; import { Badge } from "../badge"; @@ -18,10 +18,10 @@ export class PageFiltersList extends React.Component { get filters() { return pageFilters.activeFilters; } - } + }; - reset = () => pageFilters.reset() - remove = (filter: Filter) => pageFilters.removeFilter(filter) + reset = () => pageFilters.reset(); + remove = (filter: Filter) => pageFilters.removeFilter(filter); renderContent() { const { filters } = this.props; @@ -56,11 +56,11 @@ export class PageFiltersList extends React.Component { )} /> - ) + ); })} - ) + ); } render() { @@ -68,6 +68,6 @@ export class PageFiltersList extends React.Component {
{this.renderContent()}
- ) + ); } } diff --git a/src/renderer/components/item-object-list/page-filters-select.tsx b/src/renderer/components/item-object-list/page-filters-select.tsx index 5649ea48f2..3727d1824a 100644 --- a/src/renderer/components/item-object-list/page-filters-select.tsx +++ b/src/renderer/components/item-object-list/page-filters-select.tsx @@ -1,4 +1,4 @@ -import React from "react" +import React from "react"; import { observer } from "mobx-react"; import { computed } from "mobx"; import { t, Trans } from "@lingui/macro"; @@ -26,7 +26,7 @@ export class PageFiltersSelect extends React.Component { static defaultProps: Props = { allowEmpty: true, disableFilters: {}, - } + }; @computed get groupedOptions() { const options: GroupSelectOption[] = []; @@ -42,9 +42,9 @@ export class PageFiltersSelect extends React.Component { value: name, icon: , selected: selectedValues.includes(name), - } + }; }) - }) + }); } return options; } @@ -53,7 +53,7 @@ export class PageFiltersSelect extends React.Component { return this.groupedOptions.reduce((options, optGroup) => { options.push(...optGroup.options); return options; - }, []) + }, []); } private formatLabel = (option: SelectOptionFilter) => { @@ -65,7 +65,7 @@ export class PageFiltersSelect extends React.Component { {selected && } ); - } + }; private onSelect = (option: SelectOptionFilter) => { const { type, value, selected } = option; @@ -77,7 +77,7 @@ export class PageFiltersSelect extends React.Component { else { removeFilter(filter); } - } + }; render() { const { groupedOptions, formatLabel, onSelect, options } = this; @@ -98,6 +98,6 @@ export class PageFiltersSelect extends React.Component { formatOptionLabel={formatLabel} onChange={onSelect} /> - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/item-object-list/page-filters.store.ts b/src/renderer/components/item-object-list/page-filters.store.ts index 4eca16d992..6fdc536ea6 100644 --- a/src/renderer/components/item-object-list/page-filters.store.ts +++ b/src/renderer/components/item-object-list/page-filters.store.ts @@ -85,7 +85,7 @@ export class PageFiltersStore { getByType(type: FilterType, value?: any): Filter { return this.filters.find(filter => filter.type === type && ( arguments.length > 1 ? filter.value === value : true - )) + )); } getValues(type: FilterType) { diff --git a/src/renderer/components/kube-object-status-icon/index.ts b/src/renderer/components/kube-object-status-icon/index.ts index 79aecb7414..36751596a0 100644 --- a/src/renderer/components/kube-object-status-icon/index.ts +++ b/src/renderer/components/kube-object-status-icon/index.ts @@ -1 +1 @@ -export * from "./kube-object-status-icon" \ No newline at end of file +export * from "./kube-object-status-icon"; \ No newline at end of file diff --git a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx index 12e7fdb9af..a2393824ef 100644 --- a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx +++ b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx @@ -4,7 +4,7 @@ import React from "react"; import { Icon } from "../icon"; import { KubeObject } from "../../api/kube-object"; import { cssNames, formatDuration } from "../../utils"; -import { KubeObjectStatusRegistration, kubeObjectStatusRegistry } from "../../../extensions/registries/kube-object-status-registry" +import { KubeObjectStatusRegistration, kubeObjectStatusRegistry } from "../../../extensions/registries/kube-object-status-registry"; import { KubeObjectStatus, KubeObjectStatusLevel } from "../../..//extensions/renderer-api/k8s-api"; import { computed } from "mobx"; @@ -15,18 +15,18 @@ interface Props { export class KubeObjectStatusIcon extends React.Component { @computed get objectStatuses() { const { object } = this.props; - const registrations = kubeObjectStatusRegistry.getItemsForKind(object.kind, object.apiVersion) - return registrations.map((item: KubeObjectStatusRegistration) => { return item.resolve(object) }).filter((item: KubeObjectStatus) => !!item) + const registrations = kubeObjectStatusRegistry.getItemsForKind(object.kind, object.apiVersion); + return registrations.map((item: KubeObjectStatusRegistration) => { return item.resolve(object); }).filter((item: KubeObjectStatus) => !!item); } statusClassName(level: number): string { switch (level) { case KubeObjectStatusLevel.INFO: - return "info" + return "info"; case KubeObjectStatusLevel.WARNING: - return "warning" + return "warning"; case KubeObjectStatusLevel.CRITICAL: - return "error" + return "error"; default: return ""; } @@ -35,24 +35,24 @@ export class KubeObjectStatusIcon extends React.Component { statusTitle(level: number): string { switch (level) { case KubeObjectStatusLevel.INFO: - return "Info" + return "Info"; case KubeObjectStatusLevel.WARNING: - return "Warning" + return "Warning"; case KubeObjectStatusLevel.CRITICAL: - return "Critical" + return "Critical"; default: return ""; } } getAge(timestamp: string) { - if (!timestamp) return "" + if (!timestamp) return ""; const diff = new Date().getTime() - new Date(timestamp).getTime(); return formatDuration(diff, true); } renderStatuses(statuses: KubeObjectStatus[], level: number) { - const filteredStatuses = statuses.filter((item) => item.level == level) + const filteredStatuses = statuses.filter((item) => item.level == level); return filteredStatuses.length > 0 && (
@@ -64,27 +64,27 @@ export class KubeObjectStatusIcon extends React.Component {
- {status.text} · { this.getAge(status.timestamp) }
- ) + ); })}
- ) + ); } render() { - const { objectStatuses} = this - if (!objectStatuses.length) return null + const { objectStatuses} = this; + if (!objectStatuses.length) return null; const sortedStatuses = objectStatuses.sort((a: KubeObjectStatus, b: KubeObjectStatus) => { if (a.level < b.level ) { - return 1 + return 1; } if (a.level > b.level ) { - return -1 + return -1; } - return 0 - }) + return 0; + }); - const level = this.statusClassName(sortedStatuses[0].level) + const level = this.statusClassName(sortedStatuses[0].level); return ( { ) }} /> - ) + ); } } diff --git a/src/renderer/components/kube-object/index.ts b/src/renderer/components/kube-object/index.ts index b90fafab0c..a60297d225 100644 --- a/src/renderer/components/kube-object/index.ts +++ b/src/renderer/components/kube-object/index.ts @@ -1,4 +1,4 @@ -export * from "./kube-object-details" -export * from "./kube-object-list-layout" -export * from "./kube-object-menu" -export * from "./kube-object-meta" +export * from "./kube-object-details"; +export * from "./kube-object-list-layout"; +export * from "./kube-object-menu"; +export * from "./kube-object-meta"; diff --git a/src/renderer/components/kube-object/kube-object-details.tsx b/src/renderer/components/kube-object/kube-object-details.tsx index 89de7ed5da..fe5f665af1 100644 --- a/src/renderer/components/kube-object/kube-object-details.tsx +++ b/src/renderer/components/kube-object/kube-object-details.tsx @@ -1,6 +1,6 @@ -import "./kube-object-details.scss" +import "./kube-object-details.scss"; -import React from "react" +import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { computed, observable, reaction } from "mobx"; import { Trans } from "@lingui/macro"; @@ -11,7 +11,7 @@ import { Spinner } from "../spinner"; import { apiManager } from "../../api/api-manager"; import { crdStore } from "../+custom-resources/crd.store"; import { CrdResourceDetails } from "../+custom-resources"; -import { KubeObjectMenu } from "./kube-object-menu" +import { KubeObjectMenu } from "./kube-object-menu"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; export interface KubeObjectDetailsProps { @@ -25,7 +25,7 @@ export class KubeObjectDetails extends React.Component { @observable.ref loadingError: React.ReactNode; @computed get path() { - return getDetails() + return getDetails(); } @computed get object() { @@ -45,22 +45,22 @@ export class KubeObjectDetails extends React.Component { this.object, // resource might be updated via watch-event or from already opened details crdStore.items.length, // crd stores initialized after loading ], async () => { - this.loadingError = "" + this.loadingError = ""; const { path, object } = this; if (!object) { const store = apiManager.getStore(path); if (store) { - this.isLoading = true + this.isLoading = true; try { - await store.loadFromPath(path) + await store.loadFromPath(path); } catch (err) { - this.loadingError = Resource loading has failed: {err.toString()} + this.loadingError = Resource loading has failed: {err.toString()}; } finally { - this.isLoading = false + this.isLoading = false; } } } - }) + }); render() { const { object, isLoading, loadingError, isCrdInstance } = this; @@ -71,10 +71,10 @@ export class KubeObjectDetails extends React.Component { const { kind, getName } = object; title = `${kind}: ${getName()}`; details = kubeObjectDetailRegistry.getItemsForKind(object.kind, object.apiVersion).map((item, index) => { - return - }) + return ; + }); if (isCrdInstance && details.length === 0) { - details.push() + details.push(); } } return ( @@ -89,6 +89,6 @@ export class KubeObjectDetails extends React.Component { {loadingError &&
{loadingError}
} {details} - ) + ); } } diff --git a/src/renderer/components/kube-object/kube-object-list-layout.tsx b/src/renderer/components/kube-object/kube-object-list-layout.tsx index e2b49d37c4..880c933e64 100644 --- a/src/renderer/components/kube-object/kube-object-list-layout.tsx +++ b/src/renderer/components/kube-object/kube-object-list-layout.tsx @@ -25,7 +25,7 @@ export class KubeObjectListLayout extends React.Component { - return + return ; }} /> ); diff --git a/src/renderer/components/kube-object/kube-object-menu.tsx b/src/renderer/components/kube-object/kube-object-menu.tsx index 0333bf6f9c..516f6a5dd4 100644 --- a/src/renderer/components/kube-object/kube-object-menu.tsx +++ b/src/renderer/components/kube-object/kube-object-menu.tsx @@ -52,7 +52,7 @@ export class KubeObjectMenu extends React.Component { const resourceName = object.getName(); return (

Remove {resourceKind} {resourceName}?

- ) + ); } render() { @@ -61,8 +61,8 @@ export class KubeObjectMenu extends React.Component { if (!object) return null; const menuItems = kubeObjectMenuRegistry.getItemsForKind(object.kind, object.apiVersion).map((item, index) => { - return - }) + return ; + }); return ( { > {menuItems} - ) + ); } } diff --git a/src/renderer/components/kube-object/kube-object-meta.tsx b/src/renderer/components/kube-object/kube-object-meta.tsx index 78dbf74f80..0aae32ad04 100644 --- a/src/renderer/components/kube-object/kube-object-meta.tsx +++ b/src/renderer/components/kube-object/kube-object-meta.tsx @@ -23,7 +23,7 @@ export class KubeObjectMeta extends React.Component { } render() { - const object = this.props.object + const object = this.props.object; const { getName, getNs, getLabels, getResourceVersion, selfLink, getAnnotations, getFinalizers, getId, getAge, @@ -82,6 +82,6 @@ export class KubeObjectMeta extends React.Component { } - ) + ); } } diff --git a/src/renderer/components/kubeconfig-dialog/index.ts b/src/renderer/components/kubeconfig-dialog/index.ts index 2034e363a6..fdd244fe98 100644 --- a/src/renderer/components/kubeconfig-dialog/index.ts +++ b/src/renderer/components/kubeconfig-dialog/index.ts @@ -1 +1 @@ -export * from "./kubeconfig-dialog" \ No newline at end of file +export * from "./kubeconfig-dialog"; \ No newline at end of file diff --git a/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx b/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx index d75d97bbcc..74fafb2c13 100644 --- a/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx +++ b/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx @@ -46,35 +46,35 @@ export class KubeConfigDialog extends React.Component { close = () => { KubeConfigDialog.close(); - } + }; onOpen = () => { this.loadConfig(); - } + }; async loadConfig() { const config = await this.data.loader().catch(err => { - Notifications.error(err) - this.close() - }) - this.config = config ? jsYaml.dump(config) : "" + Notifications.error(err); + this.close(); + }); + this.config = config ? jsYaml.dump(config) : ""; } copyToClipboard = () => { if (this.config && copyToClipboard(this.configTextArea)) { - Notifications.ok(Config copied to clipboard) + Notifications.ok(Config copied to clipboard); } - } + }; download = () => { - downloadFile("config", this.config, "text/yaml") - } + downloadFile("config", this.config, "text/yaml"); + }; render() { const { isOpen, data = {} } = KubeConfigDialog; const { ...dialogProps } = this.props; const yamlConfig = this.config; - const header =
{data.title || Kubeconfig File}
+ const header =
{data.title || Kubeconfig File}
; const buttons = (
- ) + ); return ( { - ) + ); } } export function openServiceAccountKubeConfig(account: ServiceAccount) { - const accountName = account.getName() - const namespace = account.getNs() + const accountName = account.getName(); + const namespace = account.getNs(); KubeConfigDialog.open({ title: {accountName} kubeconfig, loader: () => apiBase.get(`/kubeconfig/service-account/${namespace}/${accountName}`) - }) + }); } \ No newline at end of file diff --git a/src/renderer/components/layout/main-layout.tsx b/src/renderer/components/layout/main-layout.tsx index baf3bd2f59..21eb5d882e 100755 --- a/src/renderer/components/layout/main-layout.tsx +++ b/src/renderer/components/layout/main-layout.tsx @@ -26,7 +26,7 @@ export class MainLayout extends React.Component { @observable isPinned = this.storage.get().pinnedSidebar; @observable isAccessible = true; - @observable sidebarWidth = this.storage.get().sidebarWidth + @observable sidebarWidth = this.storage.get().sidebarWidth; @disposeOnUnmount syncPinnedStateWithStorage = reaction( () => this.isPinned, @@ -48,12 +48,12 @@ export class MainLayout extends React.Component { getSidebarSize = () => { return { "--sidebar-width": `${this.sidebarWidth}px`, - } - } + }; + }; @autobind() adjustWidth(newWidth: number): void { - this.sidebarWidth = newWidth + this.sidebarWidth = newWidth; } render() { diff --git a/src/renderer/components/layout/page-layout.tsx b/src/renderer/components/layout/page-layout.tsx index b22470c436..c99ef6bf84 100644 --- a/src/renderer/components/layout/page-layout.tsx +++ b/src/renderer/components/layout/page-layout.tsx @@ -1,4 +1,4 @@ -import "./page-layout.scss" +import "./page-layout.scss"; import React from "react"; import { observer } from "mobx-react"; @@ -20,7 +20,7 @@ export interface PageLayoutProps extends React.DOMAttributes { const defaultProps: Partial = { provideBackButtonNavigation: true, contentGaps: true, -} +}; @observer export class PageLayout extends React.Component { @@ -51,7 +51,7 @@ export class PageLayout extends React.Component { evt.stopPropagation(); this.back(evt); } - } + }; render() { const { @@ -77,6 +77,6 @@ export class PageLayout extends React.Component { - ) + ); } } diff --git a/src/renderer/components/layout/sidebar.tsx b/src/renderer/components/layout/sidebar.tsx index b77847b4ef..428794764f 100644 --- a/src/renderer/components/layout/sidebar.tsx +++ b/src/renderer/components/layout/sidebar.tsx @@ -27,7 +27,7 @@ import { crdStore } from "../+custom-resources/crd.store"; import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resources"; import { CustomResources } from "../+custom-resources/custom-resources"; import { isActiveRoute, navigation } from "../../navigation"; -import { isAllowedResource } from "../../../common/rbac" +import { isAllowedResource } from "../../../common/rbac"; import { Spinner } from "../spinner"; import { clusterPageMenuRegistry, clusterPageRegistry, getExtensionPageUrl } from "../../../extensions/registries"; @@ -52,7 +52,7 @@ export class Sidebar extends React.Component { renderCustomResources() { if (crdStore.isLoading) { - return + return ; } return Object.entries(crdStore.groups).map(([group, crds]) => { @@ -203,7 +203,7 @@ export class Sidebar extends React.Component { text={title} icon={} isActive={isActive} /> - ) + ); })} diff --git a/src/renderer/components/layout/sub-header.tsx b/src/renderer/components/layout/sub-header.tsx index acbc17656e..360f5c5c39 100644 --- a/src/renderer/components/layout/sub-header.tsx +++ b/src/renderer/components/layout/sub-header.tsx @@ -1,4 +1,4 @@ -import "./sub-header.scss" +import "./sub-header.scss"; import React from "react"; import { cssNames } from "../../utils"; @@ -15,11 +15,11 @@ export class SubHeader extends React.Component { className = cssNames("SubHeader", { withLine, compact, - }, className) + }, className); return (
{children}
- ) + ); } } diff --git a/src/renderer/components/layout/sub-title.tsx b/src/renderer/components/layout/sub-title.tsx index f85d932b3f..ab01cb52d4 100644 --- a/src/renderer/components/layout/sub-title.tsx +++ b/src/renderer/components/layout/sub-title.tsx @@ -1,4 +1,4 @@ -import "./sub-title.scss" +import "./sub-title.scss"; import React from "react"; import { cssNames } from "../../utils"; @@ -14,11 +14,11 @@ export class SubTitle extends React.Component { let { className } = this.props; className = cssNames("SubTitle", className, { compact, - }) + }); return (
{title} {children}
- ) + ); } } diff --git a/src/renderer/components/layout/wizard-layout.tsx b/src/renderer/components/layout/wizard-layout.tsx index d9e35c2058..cd911b62ca 100644 --- a/src/renderer/components/layout/wizard-layout.tsx +++ b/src/renderer/components/layout/wizard-layout.tsx @@ -1,4 +1,4 @@ -import "./wizard-layout.scss" +import "./wizard-layout.scss"; import React from "react"; import { observer } from "mobx-react"; import { cssNames, IClassName } from "../../utils"; @@ -39,6 +39,6 @@ export class WizardLayout extends React.Component { )} - ) + ); } } diff --git a/src/renderer/components/line-progress/index.ts b/src/renderer/components/line-progress/index.ts index ae94d1710a..449fa2c9b8 100644 --- a/src/renderer/components/line-progress/index.ts +++ b/src/renderer/components/line-progress/index.ts @@ -1 +1 @@ -export * from './line-progress' \ No newline at end of file +export * from './line-progress'; \ No newline at end of file diff --git a/src/renderer/components/line-progress/line-progress.tsx b/src/renderer/components/line-progress/line-progress.tsx index 85172b16b0..c01ae5c001 100644 --- a/src/renderer/components/line-progress/line-progress.tsx +++ b/src/renderer/components/line-progress/line-progress.tsx @@ -23,7 +23,7 @@ export class LineProgress extends React.PureComponent { render() { const { className, min, max, value, precise, children, ...props } = this.props; let valuePercents = Math.min(100, value / (max - min) * 100); - const valuePercentsRounded = +valuePercents.toFixed(precise) + const valuePercentsRounded = +valuePercents.toFixed(precise); if (valuePercentsRounded) { valuePercents = valuePercentsRounded; } diff --git a/src/renderer/components/markdown-viewer/index.ts b/src/renderer/components/markdown-viewer/index.ts index 1dc81596a2..e82c6ba3c3 100644 --- a/src/renderer/components/markdown-viewer/index.ts +++ b/src/renderer/components/markdown-viewer/index.ts @@ -1 +1 @@ -export * from "./markdown-viewer" \ No newline at end of file +export * from "./markdown-viewer"; \ No newline at end of file diff --git a/src/renderer/components/menu/index.ts b/src/renderer/components/menu/index.ts index 87768fdcbf..d3ef6f3401 100644 --- a/src/renderer/components/menu/index.ts +++ b/src/renderer/components/menu/index.ts @@ -1,2 +1,2 @@ -export * from './menu' -export * from './menu-actions' +export * from './menu'; +export * from './menu-actions'; diff --git a/src/renderer/components/menu/menu-actions.tsx b/src/renderer/components/menu/menu-actions.tsx index b9ac394799..9f6908d1e9 100644 --- a/src/renderer/components/menu/menu-actions.tsx +++ b/src/renderer/components/menu/menu-actions.tsx @@ -1,4 +1,4 @@ -import "./menu-actions.scss" +import "./menu-actions.scss"; import React, { isValidElement } from "react"; import { observable } from "mobx"; @@ -25,9 +25,9 @@ export interface MenuActionsProps extends Partial { export class MenuActions extends React.Component { static defaultProps: MenuActionsProps = { get removeConfirmationMessage() { - return _i18n._(t`Remove item?`) + return _i18n._(t`Remove item?`); } - } + }; public id = uniqueId("menu_actions_"); @@ -49,7 +49,7 @@ export class MenuActions extends React.Component { ok: removeAction, labelOk: _i18n._(t`Remove`), message:
{removeConfirmationMessage}
, - }) + }); } renderTriggerIcon() { @@ -66,13 +66,13 @@ export class MenuActions extends React.Component { material: isString(triggerIcon) ? triggerIcon : undefined, active: this.isOpen, ...(typeof triggerIcon === "object" ? triggerIcon : {}), - } + }; if (iconProps.tooltip && this.isOpen) { delete iconProps.tooltip; // don't show tooltip for icon when menu is open } return ( - ) + ); } render() { @@ -113,6 +113,6 @@ export class MenuActions extends React.Component { )} - ) + ); } } diff --git a/src/renderer/components/menu/menu.tsx b/src/renderer/components/menu/menu.tsx index 1044efa810..8456a5e180 100644 --- a/src/renderer/components/menu/menu.tsx +++ b/src/renderer/components/menu/menu.tsx @@ -1,11 +1,11 @@ -import './menu.scss' +import './menu.scss'; import React, { Fragment, ReactElement, ReactNode } from "react"; import { createPortal } from "react-dom"; import { autobind, cssNames, noop } from "../../utils"; import { Animate } from "../animate"; import { Icon, IconProps } from "../icon"; -import debounce from "lodash/debounce" +import debounce from "lodash/debounce"; export const MenuContext = React.createContext(null); export type MenuContextValue = Menu; @@ -129,8 +129,8 @@ export class Menu extends React.Component { // setup initial position const position: MenuPosition = { left: true, bottom: true }; - this.elem.style.left = left + "px" - this.elem.style.top = bottom + "px" + this.elem.style.left = left + "px"; + this.elem.style.top = bottom + "px"; // correct position if menu doesn't fit to viewport const menuPos = this.elem.getBoundingClientRect(); @@ -266,7 +266,7 @@ export function SubMenu(props: Partial) { closeOnClickItem={false} {...menuProps} /> - ) + ); } export interface MenuItemProps extends React.HTMLProps { @@ -327,10 +327,10 @@ export class MenuItem extends React.Component { onClick: this.onClick, children: icon ? <> {children} : children, ref: this.bindRef, - } + }; if (this.isLink) { - return + return ; } - return
  • + return
  • ; } } diff --git a/src/renderer/components/no-items/index.ts b/src/renderer/components/no-items/index.ts index a64af80957..b1bdfc3042 100644 --- a/src/renderer/components/no-items/index.ts +++ b/src/renderer/components/no-items/index.ts @@ -1 +1 @@ -export * from "./no-items" +export * from "./no-items"; diff --git a/src/renderer/components/no-items/no-items.tsx b/src/renderer/components/no-items/no-items.tsx index 13fe3046e9..1ef643e663 100644 --- a/src/renderer/components/no-items/no-items.tsx +++ b/src/renderer/components/no-items/no-items.tsx @@ -1,4 +1,4 @@ -import "./no-items.scss" +import "./no-items.scss"; import React from "react"; import { Trans } from "@lingui/macro"; @@ -17,5 +17,5 @@ export function NoItems(props: Props) { {children || Item list is empty} - ) + ); } diff --git a/src/renderer/components/notifications/index.ts b/src/renderer/components/notifications/index.ts index 8a98afb624..1141b374e0 100644 --- a/src/renderer/components/notifications/index.ts +++ b/src/renderer/components/notifications/index.ts @@ -1,2 +1,2 @@ -export * from './notifications' -export * from './notifications.store' +export * from './notifications'; +export * from './notifications.store'; diff --git a/src/renderer/components/notifications/notifications.store.ts b/src/renderer/components/notifications/notifications.store.ts index 075f28b9d5..265e304ae6 100644 --- a/src/renderer/components/notifications/notifications.store.ts +++ b/src/renderer/components/notifications/notifications.store.ts @@ -1,7 +1,7 @@ import React from "react"; -import { action, observable } from "mobx" +import { action, observable } from "mobx"; import { autobind } from "../../utils"; -import isObject from "lodash/isObject" +import isObject from "lodash/isObject"; import uniqueId from "lodash/uniqueId"; import { JsonApiErrorParsed } from "../../api/json-api"; @@ -50,7 +50,7 @@ export class NotificationsStore { notification.id = uniqueId("notification_"); } const index = this.notifications.findIndex(item => item.id === notification.id); - if (index > -1) this.notifications.splice(index, 1, notification) + if (index > -1) this.notifications.splice(index, 1, notification); else this.notifications.push(notification); this.addAutoHideTimer(notification); } diff --git a/src/renderer/components/notifications/notifications.tsx b/src/renderer/components/notifications/notifications.tsx index a98b77ade3..44d6a90db0 100644 --- a/src/renderer/components/notifications/notifications.tsx +++ b/src/renderer/components/notifications/notifications.tsx @@ -1,13 +1,13 @@ import './notifications.scss'; -import React from 'react' +import React from 'react'; import { reaction } from "mobx"; -import { disposeOnUnmount, observer } from "mobx-react" +import { disposeOnUnmount, observer } from "mobx-react"; import { JsonApiErrorParsed } from "../../api/json-api"; import { cssNames, prevDefault } from "../../utils"; import { NotificationMessage, Notification, notificationsStore, NotificationStatus } from "./notifications.store"; import { Animate } from "../animate"; -import { Icon } from "../icon" +import { Icon } from "../icon"; @observer export class Notifications extends React.Component { @@ -18,7 +18,7 @@ export class Notifications extends React.Component { message: message, timeout: 2500, status: NotificationStatus.OK - }) + }); } static error(message: NotificationMessage) { @@ -53,7 +53,7 @@ export class Notifications extends React.Component { this.elem.scrollTo({ top: this.elem.scrollHeight, behavior: "smooth" - }) + }); } getMessage(notification: Notification) { @@ -89,9 +89,9 @@ export class Notifications extends React.Component { - ) + ); })} - ) + ); } } diff --git a/src/renderer/components/radio/radio.tsx b/src/renderer/components/radio/radio.tsx index 3dd5694c5d..6153cb5b09 100644 --- a/src/renderer/components/radio/radio.tsx +++ b/src/renderer/components/radio/radio.tsx @@ -28,7 +28,7 @@ export class RadioGroup extends React.Component { disabled: disabled !== undefined ? disabled : radio.props.disabled, checked: radio.props.value === value, onChange: onChange - } as any) + } as any); })} ); @@ -42,7 +42,7 @@ export type RadioProps = React.HTMLProps & { checked?: boolean; disabled?: boolean; onChange?(value: React.ChangeEvent): void; -} +}; export class Radio extends React.Component { private elem: HTMLElement; @@ -52,7 +52,7 @@ export class Radio extends React.Component { if (!checked && onChange) { onChange(value); } - } + }; onKeyDown = (e: React.KeyboardEvent) => { const SPACE_KEY = e.keyCode === 32; @@ -61,7 +61,7 @@ export class Radio extends React.Component { this.elem.click(); e.preventDefault(); } - } + }; render() { const { className, label, checked, children, ...inputProps } = this.props; diff --git a/src/renderer/components/resizing-anchor/index.ts b/src/renderer/components/resizing-anchor/index.ts index 6197be8d84..d99b33186b 100644 --- a/src/renderer/components/resizing-anchor/index.ts +++ b/src/renderer/components/resizing-anchor/index.ts @@ -1 +1 @@ -export * from './resizing-anchor' +export * from './resizing-anchor'; diff --git a/src/renderer/components/resizing-anchor/resizing-anchor.tsx b/src/renderer/components/resizing-anchor/resizing-anchor.tsx index a5a8ba2086..e481c89bd3 100644 --- a/src/renderer/components/resizing-anchor/resizing-anchor.tsx +++ b/src/renderer/components/resizing-anchor/resizing-anchor.tsx @@ -1,7 +1,7 @@ import "./resizing-anchor.scss"; import React from "react"; import { action, observable } from "mobx"; -import _ from "lodash" +import _ from "lodash"; import { findDOMNode } from "react-dom"; import { cssNames, noop } from "../../utils"; @@ -111,39 +111,39 @@ interface Position { * @returns the directional difference between including appropriate sign. */ function directionDelta(P1: number, P2: number, M: number): number | false { - const delta = Math.abs(M - P2) + const delta = Math.abs(M - P2); if (P1 < M) { if (P2 >= M) { // case 3 - return delta + return delta; } if (P2 < P1) { // case 2 - return -delta + return -delta; } // case 1 - return false + return false; } if (P2 < M) { // case 4 - return -delta + return -delta; } if (P1 < P2) { // case 5 - return delta + return delta; } // case 6 - return false + return false; } export class ResizingAnchor extends React.PureComponent { - @observable lastMouseEvent?: MouseEvent + @observable lastMouseEvent?: MouseEvent; @observable.ref ref?: React.RefObject; static defaultProps = { @@ -160,53 +160,53 @@ export class ResizingAnchor extends React.PureComponent { maxExtent: Number.POSITIVE_INFINITY, minExtent: 0, placement: ResizeSide.LEADING, - } - static IS_RESIZING = "resizing" + }; + static IS_RESIZING = "resizing"; constructor(props: Props) { - super(props) + super(props); if (props.maxExtent < props.minExtent) { - throw new Error("maxExtent must be >= minExtent") + throw new Error("maxExtent must be >= minExtent"); } - this.ref = React.createRef() + this.ref = React.createRef(); } componentWillUnmount() { - document.removeEventListener("mousemove", this.onDrag) - document.removeEventListener("mouseup", this.onDragEnd) + document.removeEventListener("mousemove", this.onDrag); + document.removeEventListener("mouseup", this.onDragEnd); } @action onDragInit = (event: React.MouseEvent) => { - const { onStart, onlyButtons } = this.props + const { onStart, onlyButtons } = this.props; if (typeof onlyButtons === "number" && onlyButtons !== event.buttons) { - return + return; } - document.addEventListener("mousemove", this.onDrag) - document.addEventListener("mouseup", this.onDragEnd) - document.body.classList.add(ResizingAnchor.IS_RESIZING) + document.addEventListener("mousemove", this.onDrag); + document.addEventListener("mouseup", this.onDragEnd); + document.body.classList.add(ResizingAnchor.IS_RESIZING); - this.lastMouseEvent = undefined - onStart() - } + this.lastMouseEvent = undefined; + onStart(); + }; calculateDelta(from: Position, to: Position): number | false { - const node = this.ref.current + const node = this.ref.current; if (!node) { - return false + return false; } - const boundingBox = node.getBoundingClientRect() + const boundingBox = node.getBoundingClientRect(); if (this.props.direction === ResizeDirection.HORIZONTAL) { - const barX = Math.round(boundingBox.x + (boundingBox.width / 2)) - return directionDelta(from.pageX, to.pageX, barX) + const barX = Math.round(boundingBox.x + (boundingBox.width / 2)); + return directionDelta(from.pageX, to.pageX, barX); } else { // direction === ResizeDirection.VERTICAL - const barY = Math.round(boundingBox.y + (boundingBox.height / 2)) - return directionDelta(from.pageY, to.pageY, barY) + const barY = Math.round(boundingBox.y + (boundingBox.height / 2)); + return directionDelta(from.pageY, to.pageY, barY); } } @@ -229,53 +229,53 @@ export class ResizingAnchor extends React.PureComponent { */ if (!this.lastMouseEvent) { - this.lastMouseEvent = event - return + this.lastMouseEvent = event; + return; } - const { maxExtent, minExtent, getCurrentExtent, growthDirection } = this.props - const { onDrag, onMaxExtentExceed, onMinExtentSubceed, onMaxExtentSubceed, onMinExtentExceed } = this.props - const delta = this.calculateDelta(this.lastMouseEvent, event) + const { maxExtent, minExtent, getCurrentExtent, growthDirection } = this.props; + const { onDrag, onMaxExtentExceed, onMinExtentSubceed, onMaxExtentSubceed, onMinExtentExceed } = this.props; + const delta = this.calculateDelta(this.lastMouseEvent, event); // always update the last mouse event - this.lastMouseEvent = event + this.lastMouseEvent = event; if (delta === false) { - return + return; } - const previousExtent = getCurrentExtent() - const unboundedExtent = previousExtent + (delta * growthDirection) - const boundedExtent = Math.round(Math.max(minExtent, Math.min(maxExtent, unboundedExtent))) - onDrag(boundedExtent) + const previousExtent = getCurrentExtent(); + const unboundedExtent = previousExtent + (delta * growthDirection); + const boundedExtent = Math.round(Math.max(minExtent, Math.min(maxExtent, unboundedExtent))); + onDrag(boundedExtent); if (previousExtent <= minExtent && minExtent <= unboundedExtent) { - onMinExtentExceed() + onMinExtentExceed(); } else if (previousExtent >= minExtent && minExtent >= unboundedExtent) { - onMinExtentSubceed() + onMinExtentSubceed(); } if (previousExtent <= maxExtent && maxExtent <= unboundedExtent) { - onMaxExtentExceed() + onMaxExtentExceed(); } else if (previousExtent >= maxExtent && maxExtent >= unboundedExtent) { - onMaxExtentSubceed() + onMaxExtentSubceed(); } - }, 100) + }, 100); @action onDragEnd = (_event: MouseEvent) => { - this.props.onEnd() - document.removeEventListener("mousemove", this.onDrag) - document.removeEventListener("mouseup", this.onDragEnd) - document.body.classList.remove(ResizingAnchor.IS_RESIZING) - } + this.props.onEnd(); + document.removeEventListener("mousemove", this.onDrag); + document.removeEventListener("mouseup", this.onDragEnd); + document.body.classList.remove(ResizingAnchor.IS_RESIZING); + }; render() { - const { disabled, direction, placement, onDoubleClick } = this.props + const { disabled, direction, placement, onDoubleClick } = this.props; return
    + />; } } diff --git a/src/renderer/components/resource-metrics/resource-metrics-text.tsx b/src/renderer/components/resource-metrics/resource-metrics-text.tsx index 0382e403ab..fbe57d81bf 100644 --- a/src/renderer/components/resource-metrics/resource-metrics-text.tsx +++ b/src/renderer/components/resource-metrics/resource-metrics-text.tsx @@ -11,7 +11,7 @@ interface Props { } export function ResourceMetricsText(props: Props) { - if (!props.metrics) return null + if (!props.metrics) return null; const metrics = getMetricLastPoints(props.metrics); const { cpuUsage, cpuRequests, cpuLimits, memoryUsage, memoryRequests, memoryLimits } = metrics; return ( diff --git a/src/renderer/components/resource-metrics/resource-metrics.tsx b/src/renderer/components/resource-metrics/resource-metrics.tsx index 5896c2f682..20258f30d0 100644 --- a/src/renderer/components/resource-metrics/resource-metrics.tsx +++ b/src/renderer/components/resource-metrics/resource-metrics.tsx @@ -22,7 +22,7 @@ export type IResourceMetricsValue = { object: T; tabId: number; params?: P; -} +}; export const ResourceMetricsContext = createContext(null); @@ -68,7 +68,7 @@ export function ResourceMetrics({ object, loader, interval, tabs, children, clas
    ); - } + }; return (
    diff --git a/src/renderer/components/select/index.ts b/src/renderer/components/select/index.ts index 211358f515..c7396734d3 100644 --- a/src/renderer/components/select/index.ts +++ b/src/renderer/components/select/index.ts @@ -1 +1 @@ -export * from './select' +export * from './select'; diff --git a/src/renderer/components/select/select.tsx b/src/renderer/components/select/select.tsx index b7c4b7d3d6..43cdfe1464 100644 --- a/src/renderer/components/select/select.tsx +++ b/src/renderer/components/select/select.tsx @@ -6,8 +6,8 @@ import React, { ReactNode } from "react"; import { computed } from "mobx"; import { observer } from "mobx-react"; import { autobind, cssNames } from "../../utils"; -import ReactSelect, { ActionMeta, components, Props as ReactSelectProps, Styles } from "react-select" -import Creatable, { CreatableProps } from "react-select/creatable" +import ReactSelect, { ActionMeta, components, Props as ReactSelectProps, Styles } from "react-select"; +import Creatable, { CreatableProps } from "react-select/creatable"; import { themeStore } from "../../theme.store"; const { Menu } = components; @@ -37,7 +37,7 @@ export class Select extends React.Component { autoConvertOptions: true, menuPortalTarget: document.body, menuPlacement: "auto", - } + }; @computed get theme() { return this.props.themeName || themeStore.activeTheme.type; @@ -70,7 +70,7 @@ export class Select extends React.Component { if (autoConvertOptions && Array.isArray(options)) { return options.map(opt => { return this.isValidOption(opt) ? opt : { value: opt, label: String(opt) }; - }) + }); } return options as SelectOption[]; } @@ -116,7 +116,7 @@ export class Select extends React.Component { /> ), } - } + }; return isCreatable ? : ; diff --git a/src/renderer/components/slider/index.ts b/src/renderer/components/slider/index.ts index dc1dee0239..bc79daa3ff 100644 --- a/src/renderer/components/slider/index.ts +++ b/src/renderer/components/slider/index.ts @@ -1 +1 @@ -export * from "./slider" \ No newline at end of file +export * from "./slider"; \ No newline at end of file diff --git a/src/renderer/components/slider/slider.tsx b/src/renderer/components/slider/slider.tsx index e1e180445d..c5a8aa9be6 100644 --- a/src/renderer/components/slider/slider.tsx +++ b/src/renderer/components/slider/slider.tsx @@ -37,6 +37,6 @@ export class Slider extends Component { ...this.classNames }} /> - ) + ); } } diff --git a/src/renderer/components/spinner/cube-spinner.tsx b/src/renderer/components/spinner/cube-spinner.tsx index b5632cb70a..054b8fb77f 100644 --- a/src/renderer/components/spinner/cube-spinner.tsx +++ b/src/renderer/components/spinner/cube-spinner.tsx @@ -1,5 +1,5 @@ -import './cube-spinner.scss' -import React from 'react' +import './cube-spinner.scss'; +import React from 'react'; import { cssNames } from "../../utils"; export interface CubeSpinnerProps { @@ -24,6 +24,6 @@ export class CubeSpinner extends React.Component {
    - ) + ); } } diff --git a/src/renderer/components/spinner/index.ts b/src/renderer/components/spinner/index.ts index 459e20014b..ce2d8a3a8c 100644 --- a/src/renderer/components/spinner/index.ts +++ b/src/renderer/components/spinner/index.ts @@ -1,2 +1,2 @@ -export * from './spinner' -export * from './cube-spinner' +export * from './spinner'; +export * from './cube-spinner'; diff --git a/src/renderer/components/spinner/spinner.tsx b/src/renderer/components/spinner/spinner.tsx index 0edb2665b1..3e14ae51c9 100644 --- a/src/renderer/components/spinner/spinner.tsx +++ b/src/renderer/components/spinner/spinner.tsx @@ -1,6 +1,6 @@ -import './spinner.scss' +import './spinner.scss'; -import React from 'react' +import React from 'react'; import { cssNames } from "../../utils"; export interface SpinnerProps extends React.HTMLProps { diff --git a/src/renderer/components/status-brick/index.ts b/src/renderer/components/status-brick/index.ts index 1f3f90a913..656a9a594b 100644 --- a/src/renderer/components/status-brick/index.ts +++ b/src/renderer/components/status-brick/index.ts @@ -1 +1 @@ -export * from './status-brick' \ No newline at end of file +export * from './status-brick'; \ No newline at end of file diff --git a/src/renderer/components/status-brick/status-brick.tsx b/src/renderer/components/status-brick/status-brick.tsx index 9247ac9e65..358de6e3c8 100644 --- a/src/renderer/components/status-brick/status-brick.tsx +++ b/src/renderer/components/status-brick/status-brick.tsx @@ -10,12 +10,12 @@ export interface StatusBrickProps extends React.HTMLAttributes, TooltipDeco @withTooltip export class StatusBrick extends React.Component { render() { - const { className, ...elemProps } = this.props + const { className, ...elemProps } = this.props; return (
    - ) + ); } } \ No newline at end of file diff --git a/src/renderer/components/stepper/index.ts b/src/renderer/components/stepper/index.ts index a0e715b8d2..ef1c3dd027 100644 --- a/src/renderer/components/stepper/index.ts +++ b/src/renderer/components/stepper/index.ts @@ -1 +1 @@ -export * from './stepper' +export * from './stepper'; diff --git a/src/renderer/components/table/index.ts b/src/renderer/components/table/index.ts index ad52c5f36b..cc7647bed8 100644 --- a/src/renderer/components/table/index.ts +++ b/src/renderer/components/table/index.ts @@ -1,5 +1,5 @@ -export * from './table' -export * from './table-head' -export * from './table-row' -export * from './table-cell' +export * from './table'; +export * from './table-head'; +export * from './table-row'; +export * from './table-cell'; diff --git a/src/renderer/components/table/table-cell.tsx b/src/renderer/components/table/table-cell.tsx index d278ad41d8..4264434093 100644 --- a/src/renderer/components/table/table-cell.tsx +++ b/src/renderer/components/table/table-cell.tsx @@ -46,14 +46,14 @@ export class TableCell extends React.Component { className={cssNames("sortIcon", { enabled: sortActive })} material={sortIconName} /> - ) + ); } renderCheckbox() { const { checkbox, isChecked } = this.props; const showCheckbox = isChecked !== undefined; if (checkbox && showCheckbox) { - return + return ; } } @@ -64,13 +64,13 @@ export class TableCell extends React.Component { nowrap: _nowrap, sorting: this.isSortable, }); - const content = displayBooleans(displayBoolean, title || children) + const content = displayBooleans(displayBoolean, title || children); return (
    {this.renderCheckbox()} {_nowrap ?
    {content}
    : content} {this.renderSortIcon()}
    - ) + ); } } diff --git a/src/renderer/components/table/table-head.tsx b/src/renderer/components/table/table-head.tsx index 37400c886a..7e06a48a31 100644 --- a/src/renderer/components/table/table-head.tsx +++ b/src/renderer/components/table/table-head.tsx @@ -15,7 +15,7 @@ export interface TableHeadProps extends React.DOMAttributes { export class TableHead extends React.Component { static defaultProps: TableHeadProps = { sticky: true, - } + }; render() { const { className, sticky, nowrap, showTopLine, children, ...headProps } = this.props; @@ -27,6 +27,6 @@ export class TableHead extends React.Component {
    {children}
    - ) + ); } } diff --git a/src/renderer/components/table/table-row.tsx b/src/renderer/components/table/table-row.tsx index bf22e6c0b0..dc1f1090d2 100644 --- a/src/renderer/components/table/table-row.tsx +++ b/src/renderer/components/table/table-row.tsx @@ -24,6 +24,6 @@ export class TableRow extends React.Component {
    {children}
    - ) + ); } } diff --git a/src/renderer/components/table/table.tsx b/src/renderer/components/table/table.tsx index bd88c6bca5..0822beee8d 100644 --- a/src/renderer/components/table/table.tsx +++ b/src/renderer/components/table/table.tsx @@ -9,14 +9,14 @@ import { TableHead, TableHeadElem, TableHeadProps } from "./table-head"; import { TableCellElem } from "./table-cell"; import { VirtualList } from "../virtual-list"; import { navigation, setQueryParams } from "../../navigation"; -import orderBy from "lodash/orderBy" +import orderBy from "lodash/orderBy"; import { ItemObject } from "../../item.store"; // todo: refactor + decouple search from location export type TableSortBy = string; export type TableOrderBy = "asc" | "desc" | string; -export type TableSortParams = { sortBy: TableSortBy; orderBy: TableOrderBy } +export type TableSortParams = { sortBy: TableSortBy; orderBy: TableOrderBy }; export type TableSortCallback = (data: D) => string | number | (string | number)[]; export interface TableProps extends React.DOMAttributes { @@ -51,14 +51,14 @@ export class Table extends React.Component { rowPadding: "8px", rowLineHeight: "17px", sortSyncWithUrl: true, - } + }; @observable sortParamsLocal = this.props.sortByDefault; @computed get sortParams(): Partial { if (this.props.sortSyncWithUrl) { - const sortBy = navigation.searchParams.get("sortBy") - const orderBy = navigation.searchParams.get("orderBy") + const sortBy = navigation.searchParams.get("sortBy"); + const orderBy = navigation.searchParams.get("orderBy"); return { sortBy, orderBy }; } return this.sortParamsLocal || {}; @@ -86,7 +86,7 @@ export class Table extends React.Component { _sort: this.sort, _sorting: this.sortParams, _nowrap: headElem.props.nowrap, - }) + }); }) }); } @@ -108,13 +108,13 @@ export class Table extends React.Component { protected onSort(params: TableSortParams) { const { sortSyncWithUrl, onSort } = this.props; if (sortSyncWithUrl) { - setQueryParams(params) + setQueryParams(params); } else { this.sortParamsLocal = params; } if (onSort) { - onSort(params) + onSort(params); } } @@ -139,8 +139,8 @@ export class Table extends React.Component { sortedItems = this.getSorted(sortedItems); if (rows.length) { rows = sortedItems.map(item => rows.find(row => { - return item == row.props.sortItem - })) + return item == row.props.sortItem; + })); } } if (!rows.length && !items.length && noItems) { @@ -179,6 +179,6 @@ export class Table extends React.Component { {this.renderHead()} {this.renderRows()}
    - ) + ); } } diff --git a/src/renderer/components/tabs/index.ts b/src/renderer/components/tabs/index.ts index 3fb765f1bd..c2d1b4e91b 100644 --- a/src/renderer/components/tabs/index.ts +++ b/src/renderer/components/tabs/index.ts @@ -1 +1 @@ -export * from './tabs' +export * from './tabs'; diff --git a/src/renderer/components/tabs/tabs.tsx b/src/renderer/components/tabs/tabs.tsx index e81322de1b..027631ed3d 100644 --- a/src/renderer/components/tabs/tabs.tsx +++ b/src/renderer/components/tabs/tabs.tsx @@ -12,7 +12,7 @@ interface TabsContextValue { onChange?(value: D): void; } -type Omit = Pick> +type Omit = Pick>; export interface TabsProps extends TabsContextValue, Omit, "onChange"> { className?: string; @@ -45,7 +45,7 @@ export class Tabs extends React.PureComponent { ref={this.bindRef} /> - ) + ); } } @@ -137,6 +137,6 @@ export class Tab extends React.PureComponent { {label} - ) + ); } } diff --git a/src/renderer/components/tooltip/index.ts b/src/renderer/components/tooltip/index.ts index 392f750561..049ceda2a6 100644 --- a/src/renderer/components/tooltip/index.ts +++ b/src/renderer/components/tooltip/index.ts @@ -1,2 +1,2 @@ -export * from './tooltip' -export * from './withTooltip' +export * from './tooltip'; +export * from './withTooltip'; diff --git a/src/renderer/components/tooltip/tooltip.tsx b/src/renderer/components/tooltip/tooltip.tsx index 409d5f2bd7..3d0ac4d196 100644 --- a/src/renderer/components/tooltip/tooltip.tsx +++ b/src/renderer/components/tooltip/tooltip.tsx @@ -1,7 +1,7 @@ -import './tooltip.scss' +import './tooltip.scss'; -import React from "react" -import { createPortal } from "react-dom" +import React from "react"; +import { createPortal } from "react-dom"; import { observer } from "mobx-react"; import { autobind, cssNames, IClassName } from "../../utils"; import { observable } from "mobx"; @@ -41,7 +41,7 @@ export interface TooltipContentFormatters { const defaultProps: Partial = { usePortal: true, offset: 10, -} +}; @observer export class Tooltip extends React.Component { @@ -52,25 +52,25 @@ export class Tooltip extends React.Component { @observable isVisible = !!this.props.visible; get targetElem(): HTMLElement { - return document.getElementById(this.props.targetId) + return document.getElementById(this.props.targetId); } get hoverTarget(): HTMLElement { if (this.props.tooltipOnParentHover) { - return this.targetElem.parentElement + return this.targetElem.parentElement; } - return this.targetElem + return this.targetElem; } componentDidMount() { - this.hoverTarget.addEventListener("mouseenter", this.onEnterTarget) - this.hoverTarget.addEventListener("mouseleave", this.onLeaveTarget) + this.hoverTarget.addEventListener("mouseenter", this.onEnterTarget); + this.hoverTarget.addEventListener("mouseleave", this.onLeaveTarget); } componentWillUnmount() { - this.hoverTarget.removeEventListener("mouseenter", this.onEnterTarget) - this.hoverTarget.removeEventListener("mouseleave", this.onLeaveTarget) + this.hoverTarget.removeEventListener("mouseenter", this.onEnterTarget); + this.hoverTarget.removeEventListener("mouseleave", this.onLeaveTarget); } @autobind() @@ -103,7 +103,7 @@ export class Tooltip extends React.Component { positions = new Set([ ...[preferredPositions].flat(), ...positions, - ]) + ]); } // reset position first and get all possible client-rect area for tooltip element @@ -115,7 +115,7 @@ export class Tooltip extends React.Component { // find proper position for (const pos of positions) { - const { left, top, right, bottom } = this.getPosition(pos, selfBounds, targetBounds) + const { left, top, right, bottom } = this.getPosition(pos, selfBounds, targetBounds); const fitsToWindow = left >= 0 && top >= 0 && right <= viewportWidth && bottom <= viewportHeight; if (fitsToWindow) { this.activePosition = pos; @@ -126,15 +126,15 @@ export class Tooltip extends React.Component { // apply fallback position if nothing helped from above const fallbackPosition = Array.from(positions)[0]; - const { left, top } = this.getPosition(fallbackPosition, selfBounds, targetBounds) + const { left, top } = this.getPosition(fallbackPosition, selfBounds, targetBounds); this.activePosition = fallbackPosition; this.setPosition({ left, top }); } protected setPosition(pos: { left: number, top: number }) { const elemStyle = this.elem.style; - elemStyle.left = pos.left + "px" - elemStyle.top = pos.top + "px" + elemStyle.left = pos.left + "px"; + elemStyle.top = pos.top + "px"; } protected getPosition(position: TooltipPosition, tooltipBounds: DOMRect, targetBounds: DOMRect) { @@ -202,7 +202,7 @@ export class Tooltip extends React.Component {
    {children}
    - ) + ); if (usePortal) { return createPortal(tooltip, document.body,); } diff --git a/src/renderer/components/tooltip/withTooltip.tsx b/src/renderer/components/tooltip/withTooltip.tsx index 5861e5af82..00b8eadbc6 100644 --- a/src/renderer/components/tooltip/withTooltip.tsx +++ b/src/renderer/components/tooltip/withTooltip.tsx @@ -1,10 +1,10 @@ // Tooltip decorator for simple composition with other components -import React, { HTMLAttributes, ReactNode } from "react" +import React, { HTMLAttributes, ReactNode } from "react"; import hoistNonReactStatics from "hoist-non-react-statics"; import { Tooltip, TooltipProps } from "./tooltip"; import { isReactNode } from "../../utils/isReactNode"; -import uniqueId from "lodash/uniqueId" +import uniqueId from "lodash/uniqueId"; export interface TooltipDecoratorProps { tooltip?: ReactNode | Omit; @@ -39,11 +39,11 @@ export function withTooltip>(Target: T): T { - ) + ); } return ; } - } + }; return hoistNonReactStatics(DecoratedComponent, Target) as any; } diff --git a/src/renderer/components/virtual-list/virtual-list.tsx b/src/renderer/components/virtual-list/virtual-list.tsx index 3f7288fff8..ed63a7a5ab 100644 --- a/src/renderer/components/virtual-list/virtual-list.tsx +++ b/src/renderer/components/virtual-list/virtual-list.tsx @@ -36,7 +36,7 @@ const defaultProps: Partial = { initialOffset: 1, readyOffset: 10, onScroll: noop -} +}; export class VirtualList extends Component { static defaultProps = defaultProps as object; @@ -70,8 +70,8 @@ export class VirtualList extends Component { if (parentHeight === height) return; this.setState({ height: parentHeight, - }) - }, 250) + }); + }, 250); getItemSize = (index: number) => this.props.rowHeights[index]; @@ -81,11 +81,11 @@ export class VirtualList extends Component { const index = items.findIndex(item => item.getId() == selectedItemId); if (index === -1) return; this.listRef.current.scrollToItem(index, "start"); - }) + }); scrollToItem = (index: number, align: Align) => { - this.listRef.current.scrollToItem(index, align) - } + this.listRef.current.scrollToItem(index, align); + }; render() { const { width, className, items, getRow, onScroll, outerRef } = this.props; @@ -133,4 +133,4 @@ const Row = observer((props: RowProps) => { return React.cloneElement(row, { style: Object.assign({}, row.props.style, style) }); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/renderer/components/wizard/index.ts b/src/renderer/components/wizard/index.ts index 2922b25521..c2aab1f543 100644 --- a/src/renderer/components/wizard/index.ts +++ b/src/renderer/components/wizard/index.ts @@ -1 +1 @@ -export * from './wizard' \ No newline at end of file +export * from './wizard'; \ No newline at end of file diff --git a/src/renderer/components/wizard/wizard.tsx b/src/renderer/components/wizard/wizard.tsx index 2286009f9f..1134bccd0a 100755 --- a/src/renderer/components/wizard/wizard.tsx +++ b/src/renderer/components/wizard/wizard.tsx @@ -48,7 +48,7 @@ export class Wizard extends React.Component { isLast: this.isLastStep, ...commonProps, ...stepProps - } as WizardStepProps) + } as WizardStepProps); }); } @@ -80,7 +80,7 @@ export class Wizard extends React.Component { render() { const { className, title, header, hideSteps } = this.props; - const steps = this.steps.map(stepElem => ({ title: stepElem.props.title })) + const steps = this.steps.map(stepElem => ({ title: stepElem.props.title })); const step = React.cloneElement(this.steps[this.step - 1]); return (
    @@ -136,7 +136,7 @@ export class WizardStep extends React.Component { const next = this.props.next; @@ -167,7 +167,7 @@ export class WizardStep extends React.Component { if (!this.form.noValidate) { @@ -175,14 +175,14 @@ export class WizardStep extends React.Component
    - ) + ); } render() { @@ -225,6 +225,6 @@ export class WizardStep extends React.Component - ) + ); } } diff --git a/src/renderer/hooks/index.ts b/src/renderer/hooks/index.ts index c87b336d87..860847e979 100644 --- a/src/renderer/hooks/index.ts +++ b/src/renderer/hooks/index.ts @@ -1,5 +1,5 @@ // Custom react hooks for common usage -export * from "./useStorage" -export * from "./useOnUnmount" -export * from "./useInterval" +export * from "./useStorage"; +export * from "./useOnUnmount"; +export * from "./useInterval"; diff --git a/src/renderer/hooks/useOnUnmount.ts b/src/renderer/hooks/useOnUnmount.ts index 2b3b22d05b..5af04e39b1 100644 --- a/src/renderer/hooks/useOnUnmount.ts +++ b/src/renderer/hooks/useOnUnmount.ts @@ -1,5 +1,5 @@ import { useEffect } from "react"; export function useOnUnmount(callback: () => void) { - useEffect(() => callback, []) + useEffect(() => callback, []); } \ No newline at end of file diff --git a/src/renderer/i18n.ts b/src/renderer/i18n.ts index fef42e6823..a55d2b7da1 100644 --- a/src/renderer/i18n.ts +++ b/src/renderer/i18n.ts @@ -1,7 +1,7 @@ import moment from "moment"; import { observable, reaction } from "mobx"; import { setupI18n } from "@lingui/core"; -import orderBy from "lodash/orderBy" +import orderBy from "lodash/orderBy"; import { autobind, createStorage } from "./utils"; const plurals: Record = require('make-plural/plurals'); // eslint-disable-line @typescript-eslint/no-var-requires @@ -21,7 +21,7 @@ export const _i18n = setupI18n({ @autobind() export class LocalizationStore { - readonly defaultLocale = "en" + readonly defaultLocale = "en"; @observable activeLang = this.defaultLocale; // todo: verify with package.json ling-ui "locales" diff --git a/src/renderer/kube-object.store.ts b/src/renderer/kube-object.store.ts index 16c5f0e9d0..7803ed2912 100644 --- a/src/renderer/kube-object.store.ts +++ b/src/renderer/kube-object.store.ts @@ -34,7 +34,7 @@ export abstract class KubeObjectStore extends ItemSt return this.items.find(item => { return item.getName() === name && ( namespace ? item.getNs() === namespace : true - ) + ); }); } @@ -47,13 +47,13 @@ export abstract class KubeObjectStore extends ItemSt return this.items.filter((item: T) => { const itemLabels = item.getLabels(); return labels.every(label => itemLabels.includes(label)); - }) + }); } else { return this.items.filter((item: T) => { const itemLabels = item.metadata.labels || {}; return Object.entries(labels) - .every(([key, value]) => itemLabels[key] === value) - }) + .every(([key, value]) => itemLabels[key] === value); + }); } } @@ -65,7 +65,7 @@ export abstract class KubeObjectStore extends ItemSt } else { return Promise .all(allowedNamespaces.map(namespace => this.api.list({ namespace }))) - .then(items => items.flat()) + .then(items => items.flat()); } } @@ -147,7 +147,7 @@ export abstract class KubeObjectStore extends ItemSt protected bindWatchEventsUpdater(delay = 1000) { return reaction(() => this.eventsBuffer.toJS()[0], this.updateFromEventsBuffer, { delay: delay - }) + }); } subscribe(apis = [this.api]) { diff --git a/src/renderer/lens-app.tsx b/src/renderer/lens-app.tsx index 4ed92f7ff8..78533e4f5b 100644 --- a/src/renderer/lens-app.tsx +++ b/src/renderer/lens-app.tsx @@ -1,4 +1,4 @@ -import "../common/system-ca" +import "../common/system-ca"; import React from "react"; import { ipcRenderer } from "electron"; import { Route, Router, Switch } from "react-router"; @@ -20,11 +20,11 @@ export class LensApp extends React.Component { static async init() { extensionLoader.loadOnClusterManagerRenderer(); window.addEventListener("offline", () => { - broadcastMessage("network:offline") - }) + broadcastMessage("network:offline"); + }); window.addEventListener("online", () => { - broadcastMessage("network:online") - }) + broadcastMessage("network:online"); + }); } render() { @@ -42,6 +42,6 @@ export class LensApp extends React.Component { - ) + ); } } diff --git a/src/renderer/navigation.ts b/src/renderer/navigation.ts index af4b52739f..8a9416b39c 100644 --- a/src/renderer/navigation.ts +++ b/src/renderer/navigation.ts @@ -45,10 +45,10 @@ export function getQueryString(params?: Partial, merge = true) { const searchParams = navigation.searchParams.copyWith(params); if (!merge) { Array.from(searchParams.keys()).forEach(key => { - if (!(key in params)) searchParams.delete(key) - }) + if (!(key in params)) searchParams.delete(key); + }); } - return searchParams.toString({ withPrefix: true }) + return searchParams.toString({ withPrefix: true }); } export function setQueryParams(params?: T & IQueryParams, { merge = true, replace = false } = {}) { @@ -57,11 +57,11 @@ export function setQueryParams(params?: T & IQueryParams, { merge = true, rep } export function getDetails() { - return navigation.searchParams.get("details") + return navigation.searchParams.get("details"); } export function getSelectedDetails() { - return navigation.searchParams.get("selected") || getDetails() + return navigation.searchParams.get("selected") || getDetails(); } export function getDetailsUrl(details: string) { @@ -79,20 +79,20 @@ export function showDetails(path: string, resetSelected = true) { navigation.searchParams.merge({ details: path, selected: resetSelected ? null : getSelectedDetails(), - }) + }); } /** * Hide details. Works only in renderer. */ export function hideDetails() { - showDetails(null) + showDetails(null); } export function setSearch(text: string) { navigation.replace({ search: getQueryString({ search: text }) - }) + }); } export function getSearch() { @@ -112,19 +112,19 @@ export function getMatchedClusterId(): string { if (process.isMainFrame) { // Keep track of active cluster-id for handling IPC/menus/etc. reaction(() => getMatchedClusterId(), clusterId => { - broadcastMessage("cluster-view:current-id", clusterId) + broadcastMessage("cluster-view:current-id", clusterId); }, { fireImmediately: true - }) + }); } // Handle navigation via IPC (e.g. from top menu) subscribeToBroadcast("renderer:navigate", (event, location: LocationDescriptor) => { logger.info(`[IPC]: ${event.type} ${JSON.stringify(location)}`, event); navigate(location); -}) +}); // Reload dashboard window subscribeToBroadcast("renderer:reload", () => { location.reload(); -}) +}); diff --git a/src/renderer/theme.store.ts b/src/renderer/theme.store.ts index 4b8dc5fffd..a46e84be06 100644 --- a/src/renderer/theme.store.ts +++ b/src/renderer/theme.store.ts @@ -38,7 +38,7 @@ export class ThemeStore { return { colors: {}, ...activeTheme, - } + }; } constructor() { @@ -53,7 +53,7 @@ export class ThemeStore { } }, { fireImmediately: true, - }) + }); } async init() { @@ -64,7 +64,7 @@ export class ThemeStore { } getThemeById(themeId: ThemeId): Theme { - return this.themes.find(theme => theme.id === themeId) + return this.themes.find(theme => theme.id === themeId); } protected async loadTheme(themeId: ThemeId): Promise { @@ -87,7 +87,7 @@ export class ThemeStore { protected applyTheme(theme = this.activeTheme) { if (!this.styles) { this.styles = document.createElement("style"); - this.styles.id = "lens-theme" + this.styles.id = "lens-theme"; document.head.prepend(this.styles); } const cssVars = Object.entries(theme.colors).map(([cssName, color]) => { diff --git a/src/renderer/utils/__tests__/display-booleans.test.tsx b/src/renderer/utils/__tests__/display-booleans.test.tsx index 29fdd0574b..dac75d304c 100644 --- a/src/renderer/utils/__tests__/display-booleans.test.tsx +++ b/src/renderer/utils/__tests__/display-booleans.test.tsx @@ -1,18 +1,18 @@ -import React from "react" -import { displayBooleans } from "../display-booleans" +import React from "react"; +import { displayBooleans } from "../display-booleans"; describe("displayBooleans tests", () => { it("should not do anything to div's if shouldShow is false", () => { - expect(displayBooleans(false,
    )).toStrictEqual(
    ) - }) + expect(displayBooleans(false,
    )).toStrictEqual(
    ); + }); it("should not do anything to booleans's if shouldShow is false", () => { - expect(displayBooleans(false, true)).toStrictEqual(true) - expect(displayBooleans(false, false)).toStrictEqual(false) - }) + expect(displayBooleans(false, true)).toStrictEqual(true); + expect(displayBooleans(false, false)).toStrictEqual(false); + }); it("should stringify booleans when shouldShow is true", () => { - expect(displayBooleans(true, true)).toStrictEqual("true") - expect(displayBooleans(true, false)).toStrictEqual("false") - }) -}) + expect(displayBooleans(true, true)).toStrictEqual("true"); + expect(displayBooleans(true, false)).toStrictEqual("false"); + }); +}); diff --git a/src/renderer/utils/cancelableFetch.ts b/src/renderer/utils/cancelableFetch.ts index b689adbbcd..a32e46f8a1 100644 --- a/src/renderer/utils/cancelableFetch.ts +++ b/src/renderer/utils/cancelableFetch.ts @@ -23,11 +23,11 @@ export function cancelableFetch(reqInfo: RequestInfo, reqInit: RequestInit = {}) promise.then = function (onfulfilled, onrejected) { const data = Object.getPrototypeOf(this).then.call(this, onfulfilled, onrejected); return wrapResult(data); - } + }; promise.cancel = cancel; } return result; - } + }; const req = fetch(reqInfo, { ...reqInit, signal }); return wrapResult(req); diff --git a/src/renderer/utils/convertCpu.ts b/src/renderer/utils/convertCpu.ts index 7b81a30cc3..efd6fa29ae 100644 --- a/src/renderer/utils/convertCpu.ts +++ b/src/renderer/utils/convertCpu.ts @@ -5,9 +5,9 @@ const million = thousand * thousand; const shortBillion = thousand * million; export function cpuUnitsToNumber(cpu: string) { - const cpuNum = parseInt(cpu) - if (cpu.includes("m")) return cpuNum / thousand - if (cpu.includes("u")) return cpuNum / million - if (cpu.includes("n")) return cpuNum / shortBillion - return parseFloat(cpu) + const cpuNum = parseInt(cpu); + if (cpu.includes("m")) return cpuNum / thousand; + if (cpu.includes("u")) return cpuNum / million; + if (cpu.includes("n")) return cpuNum / shortBillion; + return parseFloat(cpu); } diff --git a/src/renderer/utils/convertMemory.ts b/src/renderer/utils/convertMemory.ts index d0d7e1fc52..eb714d3142 100644 --- a/src/renderer/utils/convertMemory.ts +++ b/src/renderer/utils/convertMemory.ts @@ -1,30 +1,30 @@ // Helper to convert memory from units Ki, Mi, Gi, Ti, Pi to bytes and vise versa -const base = 1024 -const suffixes = ['K', 'M', 'G', 'T', 'P', 'E'] // Equivalents: Ki, Mi, Gi, Ti, Pi, Ei +const base = 1024; +const suffixes = ['K', 'M', 'G', 'T', 'P', 'E']; // Equivalents: Ki, Mi, Gi, Ti, Pi, Ei export function unitsToBytes(value: string) { if (!suffixes.some(suffix => value.includes(suffix))) { - return parseFloat(value) + return parseFloat(value); } const suffix = value.replace(/[0-9]|i|\./g, ''); const index = suffixes.indexOf(suffix); return parseInt( (parseFloat(value) * Math.pow(base, index + 1)).toFixed(1) - ) + ); } export function bytesToUnits(bytes: number, precision = 1) { - const sizes = ["B", ...suffixes] - const index = Math.floor(Math.log(bytes) / Math.log(base)) + const sizes = ["B", ...suffixes]; + const index = Math.floor(Math.log(bytes) / Math.log(base)); if (!bytes) { - return "N/A" + return "N/A"; } if (index === 0) { - return `${bytes}${sizes[index]}` + return `${bytes}${sizes[index]}`; } - return `${(bytes / (1024 ** index)).toFixed(precision)}${sizes[index]}i` + return `${(bytes / (1024 ** index)).toFixed(precision)}${sizes[index]}i`; } diff --git a/src/renderer/utils/copyToClipboard.ts b/src/renderer/utils/copyToClipboard.ts index 9107589f02..a04bdf9c4d 100644 --- a/src/renderer/utils/copyToClipboard.ts +++ b/src/renderer/utils/copyToClipboard.ts @@ -4,7 +4,7 @@ export function copyToClipboard(elem: HTMLElement, resetSelection = true): boole let clearSelection: () => void; if (isSelectable(elem)) { elem.select(); - clearSelection = () => elem.setSelectionRange(0, 0) + clearSelection = () => elem.setSelectionRange(0, 0); } else { const selection = window.getSelection(); diff --git a/src/renderer/utils/createStorage.ts b/src/renderer/utils/createStorage.ts index 835a31b3cc..5a0c452938 100755 --- a/src/renderer/utils/createStorage.ts +++ b/src/renderer/utils/createStorage.ts @@ -15,7 +15,7 @@ export class StorageHelper { static defaultOptions: IStorageHelperOptions = { addKeyPrefix: true, useSession: false, - } + }; constructor(protected key: string, protected defaultValue?: T, protected options?: IStorageHelperOptions) { this.options = Object.assign({}, StorageHelper.defaultOptions, options); @@ -36,7 +36,7 @@ export class StorageHelper { try { return JSON.parse(strValue); } catch (e) { - console.error(`Parsing json failed for pair: ${this.key}=${strValue}`) + console.error(`Parsing json failed for pair: ${this.key}=${strValue}`); } } return this.defaultValue; diff --git a/src/renderer/utils/cssVar.ts b/src/renderer/utils/cssVar.ts index 0be2e6880d..23485e7114 100755 --- a/src/renderer/utils/cssVar.ts +++ b/src/renderer/utils/cssVar.ts @@ -13,5 +13,5 @@ export function cssVar(elem: HTMLElement) { if (typeof value === "number") value = value + "px"; elem.style.setProperty(name, value); } - } + }; } diff --git a/src/renderer/utils/display-booleans.ts b/src/renderer/utils/display-booleans.ts index c50b7cdf9b..d9f6bdeaf2 100644 --- a/src/renderer/utils/display-booleans.ts +++ b/src/renderer/utils/display-booleans.ts @@ -1,15 +1,15 @@ -import React from "react" +import React from "react"; export function displayBooleans(shouldShow: boolean, from: React.ReactNode): React.ReactNode { if (shouldShow) { if (typeof from === "boolean") { - return from.toString() + return from.toString(); } if (Array.isArray(from)) { - return from.map(node => displayBooleans(shouldShow, node)) + return from.map(node => displayBooleans(shouldShow, node)); } } - return from + return from; } diff --git a/src/renderer/utils/downloadFile.ts b/src/renderer/utils/downloadFile.ts index d3c5e4a691..6a8b7e55e5 100644 --- a/src/renderer/utils/downloadFile.ts +++ b/src/renderer/utils/downloadFile.ts @@ -8,5 +8,5 @@ export function downloadFile(filename: string, contents: any, type: string) { document.body.appendChild(link); link.click(); document.body.removeChild(link); - URL.revokeObjectURL(url) + URL.revokeObjectURL(url); } \ No newline at end of file diff --git a/src/renderer/utils/index.ts b/src/renderer/utils/index.ts index 0c2df22c91..149d9aa1e8 100755 --- a/src/renderer/utils/index.ts +++ b/src/renderer/utils/index.ts @@ -3,19 +3,19 @@ export const noop: any = Function(); export const isElectron = !!navigator.userAgent.match(/Electron/); -export * from "../../common/utils" +export * from "../../common/utils"; -export * from "./cssVar" -export * from "./cssNames" -export * from "../../common/event-emitter" -export * from "./downloadFile" -export * from "./prevDefault" -export * from "./createStorage" -export * from "./interval" -export * from "./copyToClipboard" -export * from "./formatDuration" -export * from "./isReactNode" -export * from "./convertMemory" -export * from "./convertCpu" -export * from "./metricUnitsToNumber" -export * from "./display-booleans" +export * from "./cssVar"; +export * from "./cssNames"; +export * from "../../common/event-emitter"; +export * from "./downloadFile"; +export * from "./prevDefault"; +export * from "./createStorage"; +export * from "./interval"; +export * from "./copyToClipboard"; +export * from "./formatDuration"; +export * from "./isReactNode"; +export * from "./convertMemory"; +export * from "./convertCpu"; +export * from "./metricUnitsToNumber"; +export * from "./display-booleans"; diff --git a/src/renderer/utils/interval.ts b/src/renderer/utils/interval.ts index 17c5c2977c..37bfc7200d 100644 --- a/src/renderer/utils/interval.ts +++ b/src/renderer/utils/interval.ts @@ -26,7 +26,7 @@ export function interval(timeSec = 1, callback: IntervalCallback, autoRun = fals get isRunning() { return isRunning; } - } + }; if (autoRun) intervalManager.start(); return intervalManager; } diff --git a/src/renderer/utils/isReactNode.ts b/src/renderer/utils/isReactNode.ts index eedce9de2a..fdc0222da9 100755 --- a/src/renderer/utils/isReactNode.ts +++ b/src/renderer/utils/isReactNode.ts @@ -1,9 +1,9 @@ // Type guard for checking valid react node to use in render -import React, { ReactNode } from "react" +import React, { ReactNode } from "react"; export function isReactNode(node: ReactNode): node is ReactNode { return React.isValidElement(node) || Array.isArray(node) && node.every(isReactNode) || node == null - || typeof node !== "object" + || typeof node !== "object"; } diff --git a/src/renderer/utils/metricUnitsToNumber.ts b/src/renderer/utils/metricUnitsToNumber.ts index 9390c35b24..49d8bbcc3a 100644 --- a/src/renderer/utils/metricUnitsToNumber.ts +++ b/src/renderer/utils/metricUnitsToNumber.ts @@ -6,5 +6,5 @@ export function metricUnitsToNumber(value: string): number { const index = suffixes.indexOf(suffix); return parseInt( (parseFloat(value) * Math.pow(base, index + 1)).toFixed(1) - ) + ); } diff --git a/src/renderer/utils/prevDefault.ts b/src/renderer/utils/prevDefault.ts index 3e3857d164..bd4c4ef549 100644 --- a/src/renderer/utils/prevDefault.ts +++ b/src/renderer/utils/prevDefault.ts @@ -17,7 +17,7 @@ export function prevDefault(callback: (e evt.preventDefault(); evt.stopPropagation(); return callback(evt); - } + }; } export function stopPropagation(evt: Event | React.SyntheticEvent) { diff --git a/src/renderer/utils/rbac.ts b/src/renderer/utils/rbac.ts index 9f4ba97943..36665824aa 100644 --- a/src/renderer/utils/rbac.ts +++ b/src/renderer/utils/rbac.ts @@ -25,4 +25,4 @@ export const ResourceNames: Record = { "horizontalpodautoscalers": _i18n._("Horizontal Pod Autoscalers"), "podsecuritypolicies": _i18n._("Pod Security Policies"), "poddisruptionbudgets": _i18n._("Pod Disruption Budgets"), -} +};