From 4002844617ceaa37326da0abf3b77380aa1f761e Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Wed, 18 Aug 2021 13:38:06 +0300 Subject: [PATCH 01/33] v5.2.0-beta.2 (#3631) Signed-off-by: Jari Kolehmainen --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f12df0b69a..944ed29670 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "productName": "OpenLens", "description": "OpenLens - Open Source IDE for Kubernetes", "homepage": "https://github.com/lensapp/lens", - "version": "5.2.0-beta.1", + "version": "5.2.0-beta.2", "main": "static/build/main.js", "copyright": "© 2021 OpenLens Authors", "license": "MIT", From 21a41b7ea9265da47bce5832fa4597b243a2cf55 Mon Sep 17 00:00:00 2001 From: Lauri Nevala Date: Wed, 18 Aug 2021 14:00:06 +0300 Subject: [PATCH 02/33] Fix metrics loading on Ingress, PVC and StatefulSet details (#3632) Signed-off-by: Lauri Nevala --- .../components/+network-ingresses/ingress-details.tsx | 9 ++++++++- .../+storage-volume-claims/volume-claim-details.tsx | 10 ++++++++-- .../+workloads-statefulsets/statefulset-details.tsx | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/renderer/components/+network-ingresses/ingress-details.tsx b/src/renderer/components/+network-ingresses/ingress-details.tsx index 7fe7665041..6c762d1beb 100644 --- a/src/renderer/components/+network-ingresses/ingress-details.tsx +++ b/src/renderer/components/+network-ingresses/ingress-details.tsx @@ -23,7 +23,7 @@ import "./ingress-details.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; -import { observable, reaction } from "mobx"; +import { makeObservable, observable, reaction } from "mobx"; import { DrawerItem, DrawerTitle } from "../drawer"; import type { ILoadBalancerIngress, Ingress } from "../../../common/k8s-api/endpoints"; import { Table, TableCell, TableHead, TableRow } from "../table"; @@ -34,6 +34,7 @@ import { KubeObjectMeta } from "../kube-object-meta"; import { getBackendServiceNamePort, getMetricsForIngress, IIngressMetrics } from "../../../common/k8s-api/endpoints/ingress.api"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; +import { boundMethod } from "../../utils"; interface Props extends KubeObjectDetailsProps { } @@ -42,11 +43,17 @@ interface Props extends KubeObjectDetailsProps { export class IngressDetails extends React.Component { @observable metrics: IIngressMetrics = null; + constructor(props: Props) { + super(props); + makeObservable(this); + } + @disposeOnUnmount clean = reaction(() => this.props.object, () => { this.metrics = null; }); + @boundMethod async loadMetrics() { const { object: ingress } = this.props; 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 2836d33f91..4d515a0056 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx @@ -22,7 +22,7 @@ import "./volume-claim-details.scss"; import React, { Fragment } from "react"; -import { action, observable, reaction } from "mobx"; +import { makeObservable, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; @@ -36,6 +36,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { KubeObjectMeta } from "../kube-object-meta"; import { getDetailsUrl } from "../kube-detail-params"; +import { boundMethod } from "../../utils"; interface Props extends KubeObjectDetailsProps { } @@ -44,12 +45,17 @@ interface Props extends KubeObjectDetailsProps { export class PersistentVolumeClaimDetails extends React.Component { @observable metrics: IPvcMetrics = null; + constructor(props: Props) { + super(props); + makeObservable(this); + } + @disposeOnUnmount clean = reaction(() => this.props.object, () => { this.metrics = null; }); - @action + @boundMethod async loadMetrics() { const { object: volumeClaim } = this.props; diff --git a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx index ff116105c9..dc8581dec3 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx @@ -83,7 +83,7 @@ export class StatefulSetDetails extends React.Component {
{!isMetricHidden && podsStore.isLoaded && ( this.loadMetrics} + loader={this.loadMetrics} tabs={podMetricTabs} object={statefulSet} params={{ metrics: this.metrics }} > From 7d8a6a3e25f719a47bd89e4b7d8b6cce891e028d Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 18 Aug 2021 08:06:57 -0400 Subject: [PATCH 03/33] Validate and set defaults for HelmChart creation (#3492) --- .../k8s-api/__tests__/helm-charts.api.test.ts | 290 ++++++++++++++++++ .../k8s-api/endpoints/helm-charts.api.ts | 286 +++++++++++++++-- 2 files changed, 545 insertions(+), 31 deletions(-) create mode 100644 src/common/k8s-api/__tests__/helm-charts.api.test.ts diff --git a/src/common/k8s-api/__tests__/helm-charts.api.test.ts b/src/common/k8s-api/__tests__/helm-charts.api.test.ts new file mode 100644 index 0000000000..43efd504b3 --- /dev/null +++ b/src/common/k8s-api/__tests__/helm-charts.api.test.ts @@ -0,0 +1,290 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { anyObject } from "jest-mock-extended"; +import { HelmChart } from "../endpoints/helm-charts.api"; + +describe("HelmChart tests", () => { + describe("HelmChart.create() tests", () => { + it("should throw on non-object input", () => { + expect(() => HelmChart.create("" as any)).toThrowError('"value" must be of type object'); + expect(() => HelmChart.create(1 as any)).toThrowError('"value" must be of type object'); + expect(() => HelmChart.create(false as any)).toThrowError('"value" must be of type object'); + expect(() => HelmChart.create([] as any)).toThrowError('"value" must be of type object'); + expect(() => HelmChart.create(Symbol() as any)).toThrowError('"value" must be of type object'); + }); + + it("should throw on missing fields", () => { + expect(() => HelmChart.create({} as any)).toThrowError('"apiVersion" is required'); + expect(() => HelmChart.create({ + apiVersion: "!", + } as any)).toThrowError('"name" is required'); + expect(() => HelmChart.create({ + apiVersion: "!", + name: "!", + } as any)).toThrowError('"version" is required'); + expect(() => HelmChart.create({ + apiVersion: "!", + name: "!", + version: "!", + } as any)).toThrowError('"repo" is required'); + expect(() => HelmChart.create({ + apiVersion: "!", + name: "!", + version: "!", + repo: "!", + } as any)).toThrowError('"created" is required'); + expect(() => HelmChart.create({ + apiVersion: "!", + name: "!", + version: "!", + repo: "!", + created: "!", + } as any)).toThrowError('"digest" is required'); + }); + + it("should throw on fields being wrong type", () => { + expect(() => HelmChart.create({ + apiVersion: 1, + name: "!", + version: "!", + repo: "!", + created: "!", + digest: "!", + } as any)).toThrowError('"apiVersion" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: 1, + version: "!", + repo: "!", + created: "!", + digest: "!", + } as any)).toThrowError('"name" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "", + version: 1, + repo: "!", + created: "!", + digest: "!", + } as any)).toThrowError('"version" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: 1, + created: "!", + digest: "!", + } as any)).toThrowError('"repo" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + created: 1, + digest: "a", + } as any)).toThrowError('"created" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + created: "!", + digest: 1, + } as any)).toThrowError('"digest" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + kubeVersion: 1, + } as any)).toThrowError('"kubeVersion" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + description: 1, + } as any)).toThrowError('"description" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + home: 1, + } as any)).toThrowError('"home" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + engine: 1, + } as any)).toThrowError('"engine" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + icon: 1, + } as any)).toThrowError('"icon" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + appVersion: 1, + } as any)).toThrowError('"appVersion" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + tillerVersion: 1, + } as any)).toThrowError('"tillerVersion" must be a string'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + deprecated: 1, + } as any)).toThrowError('"deprecated" must be a boolean'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + keywords: 1, + } as any)).toThrowError('"keywords" must be an array'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + sources: 1, + } as any)).toThrowError('"sources" must be an array'); + expect(() => HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + maintainers: 1, + } as any)).toThrowError('"maintainers" must be an array'); + }); + + it("should filter non-string keywords", () => { + const chart = HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + keywords: [1, "a", false, {}, "b"] as any, + }); + + expect(chart.keywords).toStrictEqual(["a", "b"]); + }); + + it("should filter non-string sources", () => { + const chart = HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + sources: [1, "a", false, {}, "b"] as any, + }); + + expect(chart.sources).toStrictEqual(["a", "b"]); + }); + + it("should filter invalid maintainers", () => { + const chart = HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + maintainers: [{ + name: "a", + email: "b", + url: "c", + }] as any, + }); + + expect(chart.maintainers).toStrictEqual([{ + name: "a", + email: "b", + url: "c", + }]); + }); + + it("should warn on unknown fields", () => { + const { warn } = console; + const warnFn = console.warn = jest.fn(); + + HelmChart.create({ + apiVersion: "1", + name: "1", + version: "1", + repo: "1", + digest: "1", + created: "!", + maintainers: [{ + name: "a", + email: "b", + url: "c", + }] as any, + "asdjhajksdhadjks": 1, + } as any); + + expect(warnFn).toHaveBeenCalledWith("HelmChart data has unexpected fields", { + original: anyObject(), + unknownFields: ["asdjhajksdhadjks"] + }); + console.warn = warn; + }); + }); +}); diff --git a/src/common/k8s-api/endpoints/helm-charts.api.ts b/src/common/k8s-api/endpoints/helm-charts.api.ts index c7bc662b75..82d486ac81 100644 --- a/src/common/k8s-api/endpoints/helm-charts.api.ts +++ b/src/common/k8s-api/endpoints/helm-charts.api.ts @@ -22,8 +22,9 @@ import { compile } from "path-to-regexp"; import { apiBase } from "../index"; import { stringify } from "querystring"; -import { autoBind } from "../../utils"; import type { RequestInit } from "node-fetch"; +import { autoBind, bifurcateArray } from "../../utils"; +import Joi from "joi"; export type RepoHelmChartList = Record; export type HelmChartList = Record; @@ -47,7 +48,8 @@ export async function listCharts(): Promise { return Object .values(data) .reduce((allCharts, repoCharts) => allCharts.concat(Object.values(repoCharts)), []) - .map(([chart]) => HelmChart.create(chart)); + .map(([chart]) => HelmChart.create(chart, { onError: "log" })) + .filter(Boolean); } export interface GetChartDetailsOptions { @@ -66,7 +68,7 @@ export async function getChartDetails(repo: string, name: string, { version, req const path = endpoint({ repo, name }); const { readme, ...data } = await apiBase.get(`${path}?${stringify({ version })}`, undefined, reqInit); - const versions = data.versions.map(HelmChart.create); + const versions = data.versions.map(version => HelmChart.create(version, { onError: "log" })).filter(Boolean); return { readme, @@ -84,6 +86,179 @@ export async function getChartValues(repo: string, name: string, version: string return apiBase.get(`/v2/charts/${repo}/${name}/values?${stringify({ version })}`); } +export interface RawHelmChart { + apiVersion: string; + name: string; + version: string; + repo: string; + created: string; + digest: string; + kubeVersion?: string; + description?: string; + home?: string; + engine?: string; + icon?: string; + appVersion?: string; + type?: string; + tillerVersion?: string; + deprecated?: boolean; + keywords?: string[]; + sources?: string[]; + urls?: string[]; + maintainers?: HelmChartMaintainer[]; + dependencies?: RawHelmChartDependency[]; + annotations?: Record, +} + +const helmChartMaintainerValidator = Joi.object({ + name: Joi + .string() + .required(), + email: Joi + .string() + .required(), + url: Joi + .string() + .optional(), +}); + +const helmChartDependencyValidator = Joi.object({ + name: Joi + .string() + .required(), + repository: Joi + .string() + .required(), + condition: Joi + .string() + .optional(), + version: Joi + .string() + .required(), + tags: Joi + .array() + .items(Joi.string()) + .default(() => ([])), +}); + +const helmChartValidator = Joi.object({ + apiVersion: Joi + .string() + .required(), + name: Joi + .string() + .required(), + version: Joi + .string() + .required(), + repo: Joi + .string() + .required(), + created: Joi + .string() + .required(), + digest: Joi + .string() + .required(), + kubeVersion: Joi + .string() + .optional(), + description: Joi + .string() + .default(""), + home: Joi + .string() + .optional(), + engine: Joi + .string() + .optional(), + icon: Joi + .string() + .optional(), + appVersion: Joi + .string() + .optional(), + tillerVersion: Joi + .string() + .optional(), + type: Joi + .string() + .optional(), + deprecated: Joi + .boolean() + .default(false), + keywords: Joi + .array() + .items(Joi.string()) + .options({ + stripUnknown: { + arrays: true + }, + }) + .default(() => ([])), + sources: Joi + .array() + .items(Joi.string()) + .options({ + stripUnknown: { + arrays: true + }, + }) + .default(() => ([])), + urls: Joi + .array() + .items(Joi.string()) + .options({ + stripUnknown: { + arrays: true + }, + }) + .default(() => ([])), + maintainers: Joi + .array() + .items(helmChartMaintainerValidator) + .options({ + stripUnknown: { + arrays: true + }, + }) + .default(() => ([])), + dependencies: Joi + .array() + .items(helmChartDependencyValidator) + .options({ + stripUnknown: { + arrays: true + }, + }) + .default(() => ([])), + annotations: Joi + .object({}) + .pattern(/.*/, Joi.string()) + .default(() => ({})), +}); + +export interface HelmChartCreateOpts { + onError?: "throw" | "log"; +} + +export interface HelmChartMaintainer { + name: string; + email: string; + url?: string; +} + +export interface RawHelmChartDependency { + name: string; + repository: string; + condition?: string; + version: string; + tags?: string[]; +} + +export type HelmChartDependency = Required> + & Pick; + export interface HelmChart { apiVersion: string; name: string; @@ -91,74 +266,123 @@ export interface HelmChart { repo: string; kubeVersion?: string; created: string; - description?: string; + description: string; digest: string; - keywords?: string[]; + keywords: string[]; home?: string; - sources?: string[]; - maintainers?: { - name: string; - email: string; - url: string; - }[]; + sources: string[]; + urls: string[]; + annotations: Record; + dependencies: HelmChartDependency[]; + maintainers: HelmChartMaintainer[]; engine?: string; icon?: string; appVersion?: string; - deprecated?: boolean; + type?: string; + deprecated: boolean; tillerVersion?: string; } export class HelmChart { - constructor(data: HelmChart) { - Object.assign(this, data); + private constructor(value: HelmChart) { + this.apiVersion = value.apiVersion; + this.name = value.name; + this.version = value.version; + this.repo = value.repo; + this.kubeVersion = value.kubeVersion; + this.created = value.created; + this.description = value.description; + this.digest = value.digest; + this.keywords = value.keywords; + this.home = value.home; + this.sources = value.sources; + this.maintainers = value.maintainers; + this.engine = value.engine; + this.icon = value.icon; + this.apiVersion = value.apiVersion; + this.deprecated = value.deprecated; + this.tillerVersion = value.tillerVersion; + this.annotations = value.annotations; + this.urls = value.urls; + this.dependencies = value.dependencies; + this.type = value.type; + autoBind(this); } - static create(data: any) { - return new HelmChart(data); + static create(data: RawHelmChart, { onError = "throw" }: HelmChartCreateOpts = {}): HelmChart | undefined { + const result = helmChartValidator.validate(data, { + abortEarly: false, + }); + let { error } = result; + const { value } = result; + + if (!error) { + return new HelmChart(value); + } + + const [actualErrors, unknownDetails] = bifurcateArray(error.details, ({ type }) => type === "object.unknown"); + + if (unknownDetails.length > 0) { + console.warn("HelmChart data has unexpected fields", { original: data, unknownFields: unknownDetails.flatMap(d => d.path) }); + } + + if (actualErrors.length === 0) { + return new HelmChart(value); + } + + error = new Joi.ValidationError(actualErrors.map(er => er.message).join(". "), actualErrors, error._original); + + if (onError === "throw") { + throw error; + } + + console.warn("[HELM-CHART]: failed to validate data", data, error); + + return undefined; } - getId() { + getId(): string { return `${this.repo}:${this.apiVersion}/${this.name}@${this.getAppVersion()}+${this.digest}`; } - getName() { + getName(): string { return this.name; } - getFullName(splitter = "/") { - return [this.getRepository(), this.getName()].join(splitter); + getFullName(seperator = "/"): string { + return [this.getRepository(), this.getName()].join(seperator); } - getDescription() { + getDescription(): string { return this.description; } - getIcon() { + getIcon(): string | undefined { return this.icon; } - getHome() { + getHome(): string { return this.home; } - getMaintainers() { - return this.maintainers || []; + getMaintainers(): HelmChartMaintainer[] { + return this.maintainers; } - getVersion() { + getVersion(): string { return this.version; } - getRepository() { + getRepository(): string { return this.repo; } - getAppVersion() { - return this.appVersion || ""; + getAppVersion(): string | undefined { + return this.appVersion; } - getKeywords() { - return this.keywords || []; + getKeywords(): string[] { + return this.keywords; } } From dba19bb0ef88117a55a21e2ee0d2f710ccc090ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Aug 2021 13:58:44 -0400 Subject: [PATCH 04/33] Bump crypto-js from 4.0.0 to 4.1.1 (#3627) Bumps [crypto-js](https://github.com/brix/crypto-js) from 4.0.0 to 4.1.1. - [Release notes](https://github.com/brix/crypto-js/releases) - [Commits](https://github.com/brix/crypto-js/compare/4.0.0...4.1.1) --- updated-dependencies: - dependency-name: crypto-js dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 944ed29670..d160068e99 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,7 @@ "chokidar": "^3.4.3", "command-exists": "1.2.9", "conf": "^7.0.1", - "crypto-js": "^4.0.0", + "crypto-js": "^4.1.1", "electron-devtools-installer": "^3.2.0", "electron-updater": "^4.3.9", "electron-window-state": "^5.0.3", diff --git a/yarn.lock b/yarn.lock index 8f3ba1f427..dd6fab1aec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4498,10 +4498,10 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-js@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.0.0.tgz#2904ab2677a9d042856a2ea2ef80de92e4a36dcc" - integrity sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg== +crypto-js@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== crypto-random-string@^1.0.0: version "1.0.0" From 3519a521d80525fe21ba71daa3c5b3112f40f510 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Thu, 19 Aug 2021 09:23:14 +0300 Subject: [PATCH 05/33] Remove patch-package (#3640) Signed-off-by: Jari Kolehmainen --- package.json | 2 -- yarn.lock | 61 ---------------------------------------------------- 2 files changed, 63 deletions(-) diff --git a/package.json b/package.json index d160068e99..295803ee0f 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "dist": "yarn run compile && electron-builder --publish onTag", "dist:win": "yarn run compile && electron-builder --publish onTag --x64 --ia32", "dist:dir": "yarn run dist --dir -c.compression=store -c.mac.identity=null", - "postinstall": "patch-package", "download-bins": "concurrently yarn:download:*", "download:kubectl": "yarn run ts-node build/download_kubectl.ts", "download:helm": "yarn run ts-node build/download_helm.ts", @@ -352,7 +351,6 @@ "node-loader": "^1.0.3", "node-sass": "^4.14.1", "nodemon": "^2.0.12", - "patch-package": "^6.2.2", "postcss": "^8.3.6", "postcss-loader": "4.0.3", "postinstall-postinstall": "^2.1.0", diff --git a/yarn.lock b/yarn.lock index dd6fab1aec..cd2f1876ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2377,11 +2377,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - JSONStream@^1.3.4, JSONStream@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -6319,14 +6314,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" - integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== - dependencies: - fs-extra "^4.0.3" - micromatch "^3.1.4" - findup-sync@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" @@ -6477,24 +6464,6 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -8989,13 +8958,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -11187,24 +11149,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" - integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^1.2.1" - fs-extra "^7.0.1" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.0" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - path-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" @@ -13109,11 +13053,6 @@ sisteransi@^1.0.4: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" From 1410ac1fb26418118178bd26e46cd7da4b013e89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Aug 2021 08:35:47 -0400 Subject: [PATCH 06/33] Bump @types/react-dom from 17.0.6 to 17.0.9 (#3637) Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 17.0.6 to 17.0.9. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) --- updated-dependencies: - dependency-name: "@types/react-dom" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 295803ee0f..85c1b62310 100644 --- a/package.json +++ b/package.json @@ -292,7 +292,7 @@ "@types/randomcolor": "^0.5.6", "@types/react": "^17.0.0", "@types/react-beautiful-dnd": "^13.1.1", - "@types/react-dom": "^17.0.6", + "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.6", "@types/react-select": "3.1.2", "@types/react-table": "^7.7.0", diff --git a/yarn.lock b/yarn.lock index cd2f1876ce..3a90a42526 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1791,10 +1791,10 @@ dependencies: "@types/react" "*" -"@types/react-dom@*", "@types/react-dom@^17.0.6": - version "17.0.6" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.6.tgz#c158325cf91b196270bc0f4af73463f149e7eafe" - integrity sha512-MGTI+TudxAnGTj8aco8mogaPSJGK2Whje7OZh1CxNLRyhJpTZg/pGQpIbCT0eCVFQyH7UFpdvCqQEThHIp/gsA== +"@types/react-dom@*", "@types/react-dom@^17.0.9": + version "17.0.9" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.9.tgz#441a981da9d7be117042e1a6fd3dac4b30f55add" + integrity sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg== dependencies: "@types/react" "*" From b6f23c9f8bea6cb1831916842eb84e0baa7722f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:01:39 +0300 Subject: [PATCH 07/33] Bump react-virtualized-auto-sizer from 1.0.5 to 1.0.6 (#3636) Bumps [react-virtualized-auto-sizer](https://github.com/bvaughn/react-virtualized-auto-sizer) from 1.0.5 to 1.0.6. - [Release notes](https://github.com/bvaughn/react-virtualized-auto-sizer/releases) - [Commits](https://github.com/bvaughn/react-virtualized-auto-sizer/commits) --- updated-dependencies: - dependency-name: react-virtualized-auto-sizer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 85c1b62310..69a2077dd3 100644 --- a/package.json +++ b/package.json @@ -232,7 +232,7 @@ "react-dom": "^17.0.2", "react-monaco-editor": "^0.44.0", "react-router": "^5.2.0", - "react-virtualized-auto-sizer": "^1.0.5", + "react-virtualized-auto-sizer": "^1.0.6", "readable-stream": "^3.6.0", "request": "^2.88.2", "request-promise-native": "^1.0.9", diff --git a/yarn.lock b/yarn.lock index 3a90a42526..83f65c392e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12010,10 +12010,10 @@ react-transition-group@^4.3.0, react-transition-group@^4.4.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react-virtualized-auto-sizer@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.5.tgz#9eeeb8302022de56fbd7a860b08513120ce36509" - integrity sha512-kivjYVWX15TX2IUrm8F1jaCEX8EXrpy3DD+u41WGqJ1ZqbljWpiwscV+VxOM1l7sSIM1jwi2LADjhhAJkJ9dxA== +react-virtualized-auto-sizer@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" + integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ== react-window@^1.8.5: version "1.8.5" From 519d95014631a218931b250e7d78d80e4083e4ce Mon Sep 17 00:00:00 2001 From: Panu Horsmalahti Date: Thu, 19 Aug 2021 16:54:09 +0300 Subject: [PATCH 08/33] Display top bar in welcome screen. (#3643) Signed-off-by: Panu Horsmalahti --- .../+welcome/__test__/welcome.test.tsx | 55 +++++++++++++++++++ src/renderer/components/+welcome/welcome.tsx | 38 +++++++------ .../cluster-manager/welcome-topbar.tsx | 30 ++++++++++ 3 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 src/renderer/components/+welcome/__test__/welcome.test.tsx create mode 100644 src/renderer/components/cluster-manager/welcome-topbar.tsx diff --git a/src/renderer/components/+welcome/__test__/welcome.test.tsx b/src/renderer/components/+welcome/__test__/welcome.test.tsx new file mode 100644 index 0000000000..97493e07ff --- /dev/null +++ b/src/renderer/components/+welcome/__test__/welcome.test.tsx @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import React from "react"; +import { render } from "@testing-library/react"; +import "@testing-library/jest-dom/extend-expect"; +import { Welcome } from "../welcome"; +import { TopBarRegistry, WelcomeMenuRegistry } from "../../../../extensions/registries"; + +describe("", () => { + beforeEach(() => { + TopBarRegistry.createInstance(); + WelcomeMenuRegistry.createInstance(); + }); + + afterEach(() => { + TopBarRegistry.resetInstance(); + WelcomeMenuRegistry.resetInstance(); + }); + + it("renders items in the top bar", async () => { + const testId = "testId"; + const text = "topBarItem"; + + TopBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ + { + components: { + Item: () => {text} + } + } + ]); + + const { getByTestId } = render(); + + expect(await getByTestId(testId)).toHaveTextContent(text); + }); +}); diff --git a/src/renderer/components/+welcome/welcome.tsx b/src/renderer/components/+welcome/welcome.tsx index 2b06d8d255..feb676d8fd 100644 --- a/src/renderer/components/+welcome/welcome.tsx +++ b/src/renderer/components/+welcome/welcome.tsx @@ -25,32 +25,36 @@ import { observer } from "mobx-react"; import { Icon } from "../icon"; import { productName, slackUrl } from "../../../common/vars"; import { WelcomeMenuRegistry } from "../../../extensions/registries"; +import { WelcomeTopbar } from "../cluster-manager/welcome-topbar"; @observer export class Welcome extends React.Component { render() { return ( -
-
- + <> + +
+
+ -

Welcome to {productName} 5!

+

Welcome to {productName} 5!

-

- To get you started we have auto-detected your clusters in your kubeconfig file and added them to the catalog, your centralized view for managing all your cloud-native resources. -

- If you have any questions or feedback, please join our Lens Community slack channel. -

+

+ To get you started we have auto-detected your clusters in your kubeconfig file and added them to the catalog, your centralized view for managing all your cloud-native resources. +

+ If you have any questions or feedback, please join our Lens Community slack channel. +

- + +
-
+ ); } } diff --git a/src/renderer/components/cluster-manager/welcome-topbar.tsx b/src/renderer/components/cluster-manager/welcome-topbar.tsx new file mode 100644 index 0000000000..c528326c7a --- /dev/null +++ b/src/renderer/components/cluster-manager/welcome-topbar.tsx @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import React from "react"; +import { TopBar } from "../layout/topbar"; + +export function WelcomeTopbar() { + return ( + + + ); +} From 43c38b714bb20802f1a5ce5d6f3aebde3db8f45a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Aug 2021 10:59:29 -0400 Subject: [PATCH 09/33] Bump @kubernetes/client-node from 0.14.3 to 0.15.1 (#3638) Bumps [@kubernetes/client-node](https://github.com/kubernetes-client/javascript) from 0.14.3 to 0.15.1. - [Release notes](https://github.com/kubernetes-client/javascript/releases) - [Changelog](https://github.com/kubernetes-client/javascript/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes-client/javascript/compare/0.14.3...0.15.1) --- updated-dependencies: - dependency-name: "@kubernetes/client-node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 85 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 69a2077dd3..1575672ae3 100644 --- a/package.json +++ b/package.json @@ -182,7 +182,7 @@ "dependencies": { "@hapi/call": "^8.0.1", "@hapi/subtext": "^7.0.3", - "@kubernetes/client-node": "^0.14.3", + "@kubernetes/client-node": "^0.15.1", "@sentry/electron": "^2.5.0", "@sentry/integrations": "^6.10.0", "abort-controller": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index 83f65c392e..9739cc1c97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -797,12 +797,12 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@kubernetes/client-node@^0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-0.14.3.tgz#5ed9b88873419080547f22cb74eb502bf6671fca" - integrity sha512-9hHGDNm2JEFQcRTpDxVoAVr0fowU+JH/l5atCXY9VXwvFM18pW5wr2LzLP+Q2Rh+uQv7Moz4gEjEKSCgVKykEQ== +"@kubernetes/client-node@^0.15.1": + version "0.15.1" + resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-0.15.1.tgz#617357873d20de348a99227f3b699c2adb765152" + integrity sha512-j3o5K4TWkdrX2yDndbEZcDxhgea6O2JKnesWoYCJ64WtMn2GbQXGBOnkn2i0WT2MugGbLR+qCm8Y3oHWBApaTA== dependencies: - "@types/js-yaml" "^3.12.1" + "@types/js-yaml" "^4.0.1" "@types/node" "^10.12.0" "@types/request" "^2.47.1" "@types/stream-buffers" "^3.0.3" @@ -810,14 +810,14 @@ "@types/underscore" "^1.8.9" "@types/ws" "^6.0.1" byline "^5.0.0" - execa "1.0.0" + execa "5.0.0" isomorphic-ws "^4.0.1" - js-yaml "^3.13.1" + js-yaml "^4.1.0" jsonpath-plus "^0.19.0" openid-client "^4.1.1" request "^2.88.0" rfc4648 "^1.3.0" - shelljs "^0.8.2" + shelljs "^0.8.4" stream-buffers "^3.0.2" tar "^6.0.2" tmp-promise "^3.0.2" @@ -1575,11 +1575,16 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/js-yaml@^3.12.1", "@types/js-yaml@^3.12.4": +"@types/js-yaml@^3.12.4": version "3.12.4" resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.4.tgz#7d3b534ec35a0585128e2d332db1403ebe057e25" integrity sha512-fYMgzN+9e28R81weVN49inn/u798ruU91En1ZnGvSZzCRc5jXx9B2EDhlRaWmcO1RIxFHL8AajRXzxDuJu93+A== +"@types/js-yaml@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.2.tgz#4117a7a378593a218e9d6f0ef44ce6d5d9edf7fa" + integrity sha512-KbeHS/Y4R+k+5sWXEYzAZKuB1yQlZtEghuhRxrVRLaqhtoG5+26JwQsa4HyS3AWX8v1Uwukma5HheduUDskasA== + "@types/jsdom@^16.2.4": version "16.2.4" resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.4.tgz#527ca99943e00561ca4056b1904fd5f4facebc3b" @@ -4467,7 +4472,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5888,18 +5893,20 @@ exec-sh@^0.3.2: resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== -execa@1.0.0, execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== +execa@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376" + integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ== dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" execa@^0.7.0: version "0.7.0" @@ -5914,6 +5921,19 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" @@ -6676,6 +6696,11 @@ get-stream@^5.0.0, get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -7331,6 +7356,11 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -10433,7 +10463,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.0: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -10775,6 +10805,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + onigasm@^2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/onigasm/-/onigasm-2.2.5.tgz#cc4d2a79a0fa0b64caec1f4c7ea367585a676892" @@ -12991,7 +13028,7 @@ shell-env@^3.0.1: execa "^1.0.0" strip-ansi "^5.2.0" -shelljs@^0.8.2: +shelljs@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== @@ -13022,7 +13059,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== From 902224a6dc479b99f446449722c36432fb90f7bd Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 19 Aug 2021 13:40:16 -0400 Subject: [PATCH 10/33] Always display a Node's taints' values (#3646) Signed-off-by: Sebastian Malton --- src/renderer/components/+nodes/node-details.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/components/+nodes/node-details.tsx b/src/renderer/components/+nodes/node-details.tsx index 9e86939260..cc858cba46 100644 --- a/src/renderer/components/+nodes/node-details.tsx +++ b/src/renderer/components/+nodes/node-details.tsx @@ -134,7 +134,7 @@ export class NodeDetails extends React.Component { { taints.map(({ key, effect, value }) => ( - + )) } From 2716a3fded819c79bcad481f8dc048a437930180 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 19 Aug 2021 14:29:18 -0400 Subject: [PATCH 11/33] Fix .eslintrc.js (#3648) Signed-off-by: Sebastian Malton --- .eslintrc.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 8bdc4d473e..1426f74e7f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -26,6 +26,7 @@ module.exports = { "**/node_modules/**/*", "**/dist/**/*", "**/static/**/*", + "**/site/**/*", ], settings: { react: { @@ -114,7 +115,7 @@ module.exports = { "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-unused-vars": "off", - "unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warning", + "unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn", "unused-imports/no-unused-vars-ts": [ "warn", { "vars": "all", @@ -182,7 +183,7 @@ module.exports = { "@typescript-eslint/no-empty-function": "off", "react/display-name": "off", "@typescript-eslint/no-unused-vars": "off", - "unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warning", + "unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn", "unused-imports/no-unused-vars-ts": [ "warn", { "vars": "all", From d3ce43e73d21ae808f93b19e86573d3862478a88 Mon Sep 17 00:00:00 2001 From: chh <1474479+chenhunghan@users.noreply.github.com> Date: Mon, 23 Aug 2021 14:31:24 +0300 Subject: [PATCH 12/33] Add 'welcome banner' extension API (#3656) * Add react-material-ui-carousel Signed-off-by: Hung-Han (Henry) Chen * Add welcomeBanners extension api Signed-off-by: Hung-Han (Henry) Chen --- package.json | 1 + src/extensions/extension-loader.ts | 1 + src/extensions/lens-renderer-extension.ts | 1 + src/extensions/registries/index.ts | 1 + .../registries/welcome-banner-registry.ts | 35 +++++++++++++++++++ src/main/window-manager.ts | 30 ++++++++++++++++ .../+welcome/__test__/welcome.test.tsx | 25 ++++++++++--- src/renderer/components/+welcome/welcome.tsx | 18 ++++++++-- src/renderer/initializers/registries.ts | 1 + yarn.lock | 34 ++++++++++++++++++ 10 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 src/extensions/registries/welcome-banner-registry.ts diff --git a/package.json b/package.json index 1575672ae3..7089d08a72 100644 --- a/package.json +++ b/package.json @@ -230,6 +230,7 @@ "proper-lockfile": "^4.1.2", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-material-ui-carousel": "^2.3.1", "react-monaco-editor": "^0.44.0", "react-router": "^5.2.0", "react-virtualized-auto-sizer": "^1.0.6", diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts index 321ab80259..0f860a964d 100644 --- a/src/extensions/extension-loader.ts +++ b/src/extensions/extension-loader.ts @@ -278,6 +278,7 @@ export class ExtensionLoader extends Singleton { registries.StatusBarRegistry.getInstance().add(extension.statusBarItems), registries.CommandRegistry.getInstance().add(extension.commands), registries.WelcomeMenuRegistry.getInstance().add(extension.welcomeMenus), + registries.WelcomeBannerRegistry.getInstance().add(extension.welcomeBanners), registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems), registries.TopBarRegistry.getInstance().add(extension.topBarItems), ]; diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index dd5670fd67..0ae8a44323 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -38,6 +38,7 @@ export class LensRendererExtension extends LensExtension { kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = []; commands: registries.CommandRegistration[] = []; welcomeMenus: registries.WelcomeMenuRegistration[] = []; + welcomeBanners: registries.WelcomeBannerRegistration[] = []; catalogEntityDetailItems: registries.CatalogEntityDetailRegistration[] = []; topBarItems: registries.TopBarRegistration[] = []; diff --git a/src/extensions/registries/index.ts b/src/extensions/registries/index.ts index febc0ba7ca..99809265a2 100644 --- a/src/extensions/registries/index.ts +++ b/src/extensions/registries/index.ts @@ -32,6 +32,7 @@ export * from "./kube-object-status-registry"; export * from "./command-registry"; export * from "./entity-setting-registry"; export * from "./welcome-menu-registry"; +export * from "./welcome-banner-registry"; export * from "./catalog-entity-detail-registry"; export * from "./workloads-overview-detail-registry"; export * from "./topbar-registry"; diff --git a/src/extensions/registries/welcome-banner-registry.ts b/src/extensions/registries/welcome-banner-registry.ts new file mode 100644 index 0000000000..ef36da8444 --- /dev/null +++ b/src/extensions/registries/welcome-banner-registry.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { BaseRegistry } from "./base-registry"; + +/** + * WelcomeBannerRegistration is for an extension to register + * Provide a Banner component to be renderered in the welcome screen. + */ +export interface WelcomeBannerRegistration { + /** + * The banner component to be shown on the welcome screen. + */ + Banner?: React.ComponentType +} + +export class WelcomeBannerRegistry extends BaseRegistry { } diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index 88d7dff0af..f1715a4284 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -89,6 +89,7 @@ export class WindowManager extends Singleton { nodeIntegration: true, nodeIntegrationInSubFrames: true, enableRemoteModule: true, + webviewTag: true }, }); this.windowState.manage(this.mainWindow); @@ -121,6 +122,35 @@ export class WindowManager extends Singleton { }) .on("did-finish-load", () => { logger.info("[WINDOW-MANAGER]: Main window loaded"); + }) + .on("will-attach-webview", (event, webPreferences, params) => { + logger.info("[WINDOW-MANAGER]: Attaching webview"); + // Following is security recommendations because we allow webview tag (webviewTag: true) + // suggested by https://www.electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation + // and https://www.electronjs.org/docs/tutorial/security#10-do-not-use-allowpopups + + if (webPreferences.preload) { + logger.warn("[WINDOW-MANAGER]: Strip away preload scripts of webview"); + delete webPreferences.preload; + } + + // @ts-expect-error some electron version uses webPreferences.preloadURL/webPreferences.preload + if (webPreferences.preloadURL) { + logger.warn("[WINDOW-MANAGER]: Strip away preload scripts of webview"); + delete webPreferences.preload; + } + + if (params.allowpopups) { + logger.warn("[WINDOW-MANAGER]: We do not allow allowpopups props, stop webview from renderer"); + + // event.preventDefault() will destroy the guest page. + event.preventDefault(); + + return; + } + + // Always disable Node.js integration for all webviews + webPreferences.nodeIntegration = false; }); } diff --git a/src/renderer/components/+welcome/__test__/welcome.test.tsx b/src/renderer/components/+welcome/__test__/welcome.test.tsx index 97493e07ff..52f579643f 100644 --- a/src/renderer/components/+welcome/__test__/welcome.test.tsx +++ b/src/renderer/components/+welcome/__test__/welcome.test.tsx @@ -20,20 +20,22 @@ */ import React from "react"; -import { render } from "@testing-library/react"; +import { render, screen } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; import { Welcome } from "../welcome"; -import { TopBarRegistry, WelcomeMenuRegistry } from "../../../../extensions/registries"; +import { TopBarRegistry, WelcomeMenuRegistry, WelcomeBannerRegistry } from "../../../../extensions/registries"; describe("", () => { beforeEach(() => { TopBarRegistry.createInstance(); WelcomeMenuRegistry.createInstance(); + WelcomeBannerRegistry.createInstance(); }); afterEach(() => { TopBarRegistry.resetInstance(); WelcomeMenuRegistry.resetInstance(); + WelcomeBannerRegistry.resetInstance(); }); it("renders items in the top bar", async () => { @@ -48,8 +50,23 @@ describe("", () => { } ]); - const { getByTestId } = render(); + render(); - expect(await getByTestId(testId)).toHaveTextContent(text); + expect(screen.getByTestId(testId)).toHaveTextContent(text); + }); + + it("renders registered in WelcomeBannerRegistry and hide logo", async () => { + const testId = "testId"; + + WelcomeBannerRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ + { + Banner: () =>
+ } + ]); + + const { container } = render(); + + expect(screen.queryByTestId(testId)).toBeInTheDocument(); + expect(container.getElementsByClassName("logo").length).toBe(0); }); }); diff --git a/src/renderer/components/+welcome/welcome.tsx b/src/renderer/components/+welcome/welcome.tsx index feb676d8fd..ffb290fb09 100644 --- a/src/renderer/components/+welcome/welcome.tsx +++ b/src/renderer/components/+welcome/welcome.tsx @@ -22,20 +22,34 @@ import "./welcome.scss"; import React from "react"; import { observer } from "mobx-react"; +import Carousel from "react-material-ui-carousel"; import { Icon } from "../icon"; import { productName, slackUrl } from "../../../common/vars"; import { WelcomeMenuRegistry } from "../../../extensions/registries"; import { WelcomeTopbar } from "../cluster-manager/welcome-topbar"; +import { WelcomeBannerRegistry } from "../../../extensions/registries"; @observer export class Welcome extends React.Component { render() { + const welcomeBanner = WelcomeBannerRegistry.getInstance().getItems(); + return ( <> -
+
- + {welcomeBanner.length > 0 ? ( + 1} + autoPlay={true} + > + {welcomeBanner.map((item, index) => + + )} + + ) : }

Welcome to {productName} 5!

diff --git a/src/renderer/initializers/registries.ts b/src/renderer/initializers/registries.ts index 1d455a0bcc..3063213bc8 100644 --- a/src/renderer/initializers/registries.ts +++ b/src/renderer/initializers/registries.ts @@ -34,6 +34,7 @@ export function initRegistries() { registries.KubeObjectStatusRegistry.createInstance(); registries.StatusBarRegistry.createInstance(); registries.WelcomeMenuRegistry.createInstance(); + registries.WelcomeBannerRegistry.createInstance(); registries.WorkloadsOverviewDetailRegistry.createInstance(); registries.TopBarRegistry.createInstance(); } diff --git a/yarn.lock b/yarn.lock index 9739cc1c97..606325daee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1875,6 +1875,15 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/react@^16.8.12": + version "16.14.14" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.14.tgz#853de95a32a6a0e719192e222eacad024add2b8e" + integrity sha512-uwIWDYW8LznHzEMJl7ag9St1RsK0gw/xaFZ5+uI1ZM1HndwUgmPH3/wQkSb87GkOVg7shUxnpNW8DcN0AzvG5Q== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/readable-stream@^2.3.9": version "2.3.9" resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.9.tgz#40a8349e6ace3afd2dd1b6d8e9b02945de4566a9" @@ -1917,6 +1926,11 @@ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "@types/semver@^7.2.0", "@types/semver@^7.3.5": version "7.3.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.8.tgz#508a27995498d7586dcecd77c25e289bfaf90c59" @@ -2940,6 +2954,13 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +auto-bind@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-2.1.1.tgz#8ae509671ecdfbd5009fc99b0f19ae9c3a2abf50" + integrity sha512-NUwV1i9D3vxxY1KnfZgSZ716d6ovY7o8LfOwLhGIPFBowIb6Ln6DBW64+jCqPzUznel2hRSkQnYQqvh7/ldw8A== + dependencies: + "@types/react" "^16.8.12" + auto-bind@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" @@ -11957,6 +11978,14 @@ react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== +react-material-ui-carousel@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/react-material-ui-carousel/-/react-material-ui-carousel-2.3.1.tgz#73b516f831d45df70bb9219f56fee14a2788e332" + integrity sha512-QV3z+x10x19rSAPSHMmkHtdx/PSiwqo6FeAaY8Y04LtuKM0ZxHsgeMslNdcI8M1G2B48391YqN+ouWFPYqAbTA== + dependencies: + auto-bind "^2.1.1" + react-swipeable "^6.1.0" + react-monaco-editor@^0.44.0: version "0.44.0" resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.44.0.tgz#9f966fd00b6c30e8be8873a3fbc86f14a0da2ba4" @@ -12032,6 +12061,11 @@ react-select@3.2.0: react-input-autosize "^3.0.0" react-transition-group "^4.3.0" +react-swipeable@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/react-swipeable/-/react-swipeable-6.2.0.tgz#057271cb7a6fb4af9d2a3f6d80ccdf33e2f64d47" + integrity sha512-nWQ8dEM8e/uswZLSIkXUsAnQmnX4MTcryOHBQIQYRMJFDpgDBSiVbKsz/BZVCIScF4NtJh16oyxwaNOepR6xSw== + react-table@^7.7.0: version "7.7.0" resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.7.0.tgz#e2ce14d7fe3a559f7444e9ecfe8231ea8373f912" From 7b48ab02790331c6135b435f7aa4cf43d68629c8 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Mon, 23 Aug 2021 15:27:54 +0300 Subject: [PATCH 13/33] Do not copy if title isn't of type 'string' (#3657) Signed-off-by: Alex Andreev --- .../components/+apps-helm-charts/helm-chart-details.tsx | 2 +- src/renderer/components/+apps-releases/release-details.tsx | 2 +- src/renderer/components/drawer/drawer.tsx | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) 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 d1a152808a..1cedc10d3f 100644 --- a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx +++ b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx @@ -173,7 +173,7 @@ export class HelmChartDetails extends Component { render() { const { chart, hideDetails } = this.props; - const title = chart ? <>Chart: {chart.getFullName()} : ""; + const title = chart ? `Chart: ${chart.getFullName()}` : ""; return ( { render() { const { release, hideDetails } = this.props; - const title = release ? <>Release: {release.getName()} : ""; + const title = release ? `Release: ${release.getName()}` : ""; const toolbar = ; return ( diff --git a/src/renderer/components/drawer/drawer.tsx b/src/renderer/components/drawer/drawer.tsx index 45591e65be..42a6eecd87 100644 --- a/src/renderer/components/drawer/drawer.tsx +++ b/src/renderer/components/drawer/drawer.tsx @@ -163,7 +163,9 @@ export class Drawer extends React.Component {
{title} - + {typeof title == "string" && ( + + )}
{toolbar} From 4fd0796687a207360f16318cd24550909eb856b4 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Mon, 23 Aug 2021 15:47:13 +0300 Subject: [PATCH 14/33] @material-ui/lab version bump (#3658) Signed-off-by: Alex Andreev --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7089d08a72..ef36797605 100644 --- a/package.json +++ b/package.json @@ -256,7 +256,7 @@ "@emeraldpay/hashicon-react": "^0.4.0", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", - "@material-ui/lab": "^4.0.0-alpha.57", + "@material-ui/lab": "^4.0.0-alpha.60", "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", "@sentry/react": "^6.8.0", "@sentry/types": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index 606325daee..43c640b062 100644 --- a/yarn.lock +++ b/yarn.lock @@ -857,10 +857,10 @@ dependencies: "@babel/runtime" "^7.4.4" -"@material-ui/lab@^4.0.0-alpha.57": - version "4.0.0-alpha.57" - resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.57.tgz#e8961bcf6449e8a8dabe84f2700daacfcafbf83a" - integrity sha512-qo/IuIQOmEKtzmRD2E4Aa6DB4A87kmY6h0uYhjUmrrgmEAgbbw9etXpWPVXuRK6AGIQCjFzV6WO2i21m1R4FCw== +"@material-ui/lab@^4.0.0-alpha.60": + version "4.0.0-alpha.60" + resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz#5ad203aed5a8569b0f1753945a21a05efa2234d2" + integrity sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/utils" "^4.11.2" From 07969ef7d7fdb72f2effe5a23a065d39cb18c846 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 09:15:14 -0400 Subject: [PATCH 15/33] Bump jest-canvas-mock from 2.3.0 to 2.3.1 (#3652) Bumps [jest-canvas-mock](https://github.com/hustcc/jest-canvas-mock) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/hustcc/jest-canvas-mock/releases) - [Changelog](https://github.com/hustcc/jest-canvas-mock/blob/master/CHANGELOG.md) - [Commits](https://github.com/hustcc/jest-canvas-mock/commits) --- updated-dependencies: - dependency-name: jest-canvas-mock dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ef36797605..c04ca5b9de 100644 --- a/package.json +++ b/package.json @@ -344,7 +344,7 @@ "identity-obj-proxy": "^3.0.0", "include-media": "^1.4.9", "jest": "26.6.3", - "jest-canvas-mock": "^2.3.0", + "jest-canvas-mock": "^2.3.1", "jest-fetch-mock": "^3.0.3", "jest-mock-extended": "^1.0.16", "make-plural": "^6.2.2", diff --git a/yarn.lock b/yarn.lock index 43c640b062..9d5edc1f5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8255,10 +8255,10 @@ jake@^10.6.1: filelist "^1.0.1" minimatch "^3.0.4" -jest-canvas-mock@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.3.0.tgz#50f4cc178ae52c4c0e2ce4fd3a3ad2a41ad4eb36" - integrity sha512-3TMyR66VG2MzAW8Negzec03bbcIjVJMfGNvKzrEnbws1CYKqMNkvIJ8LbkoGYfp42tKqDmhIpQq3v+MNLW2A2w== +jest-canvas-mock@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.3.1.tgz#9535d14bc18ccf1493be36ac37dd349928387826" + integrity sha512-5FnSZPrX3Q2ZfsbYNE3wqKR3+XorN8qFzDzB5o0golWgt6EOX1+emBnpOc9IAQ+NXFj8Nzm3h7ZdE/9H0ylBcg== dependencies: cssfontparser "^1.2.1" moo-color "^1.0.2" From ec57425c86d6e12f8faa6805854ddba6edfd94a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 09:27:26 -0400 Subject: [PATCH 16/33] Bump tar from 6.1.4 to 6.1.10 (#3651) Bumps [tar](https://github.com/npm/node-tar) from 6.1.4 to 6.1.10. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v6.1.4...v6.1.10) --- updated-dependencies: - dependency-name: tar dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c04ca5b9de..3bfb2d59f6 100644 --- a/package.json +++ b/package.json @@ -241,7 +241,7 @@ "serializr": "^2.0.3", "shell-env": "^3.0.1", "spdy": "^4.0.2", - "tar": "^6.1.4", + "tar": "^6.1.10", "tcp-port-used": "^1.0.1", "tempy": "^0.5.0", "url-parse": "^1.5.1", diff --git a/yarn.lock b/yarn.lock index 9d5edc1f5f..ef9b57c178 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13944,10 +13944,10 @@ tar@^4.4.10, tar@^4.4.12, tar@^4.4.13: safe-buffer "^5.1.2" yallist "^3.0.3" -tar@^6.0.2, tar@^6.1.4: - version "6.1.4" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.4.tgz#9f0722b772a5e00dba7d52e1923b37a7ec3799b3" - integrity sha512-kcPWrO8S5ABjuZ/v1xQHP8xCEvj1dQ1d9iAb6Qs4jLYzaAIYWwST2IQpz7Ud8VNYRI+fGhFjrnzRKmRggKWg3g== +tar@^6.0.2, tar@^6.1.10: + version "6.1.10" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.10.tgz#8a320a74475fba54398fa136cd9883aa8ad11175" + integrity sha512-kvvfiVvjGMxeUNB6MyYv5z7vhfFRwbwCXJAeL0/lnbrttBVqcMOnpHUf0X42LrPMR8mMpgapkJMchFH4FSHzNA== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" From b780834c2a94c999df7075c1c708e2b421b9c1ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 09:27:51 -0400 Subject: [PATCH 17/33] Bump webpack-dev-server from 3.11.0 to 3.11.2 (#3650) Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 3.11.0 to 3.11.2. - [Release notes](https://github.com/webpack/webpack-dev-server/releases) - [Changelog](https://github.com/webpack/webpack-dev-server/blob/v3.11.2/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-server/compare/v3.11.0...v3.11.2) --- updated-dependencies: - dependency-name: webpack-dev-server dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 80 ++++++++++++++++++++++------------------------------ 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 3bfb2d59f6..a0b4b11afe 100644 --- a/package.json +++ b/package.json @@ -383,7 +383,7 @@ "url-loader": "^4.1.1", "webpack": "^4.46.0", "webpack-cli": "^3.3.12", - "webpack-dev-server": "^3.11.0", + "webpack-dev-server": "^3.11.2", "webpack-node-externals": "^1.7.2", "what-input": "^5.2.10", "xterm": "^4.12.0", diff --git a/yarn.lock b/yarn.lock index ef9b57c178..3de229cfae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4734,7 +4734,7 @@ debug@4.1.0: dependencies: ms "^2.1.1" -debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -6178,17 +6178,10 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -faye-websocket@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= - dependencies: - websocket-driver ">=0.5.1" - -faye-websocket@~0.11.1: - version "0.11.3" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" - integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== dependencies: websocket-driver ">=0.5.1" @@ -8808,7 +8801,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@^3.3.2: +json3@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== @@ -12849,10 +12842,10 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -selfsigned@^1.10.7: - version "1.10.8" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" - integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== +selfsigned@^1.10.8: + version "1.10.11" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" + integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== dependencies: node-forge "^0.10.0" @@ -13185,26 +13178,26 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" - integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== +sockjs-client@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6" + integrity sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ== dependencies: - debug "^3.2.5" + debug "^3.2.6" eventsource "^1.0.7" - faye-websocket "~0.11.1" - inherits "^2.0.3" - json3 "^3.3.2" - url-parse "^1.4.3" + faye-websocket "^0.11.3" + inherits "^2.0.4" + json3 "^3.3.3" + url-parse "^1.5.1" -sockjs@0.3.20: - version "0.3.20" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" - integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== +sockjs@^0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== dependencies: - faye-websocket "^0.10.0" + faye-websocket "^0.11.3" uuid "^3.4.0" - websocket-driver "0.6.5" + websocket-driver "^0.7.4" socks-proxy-agent@^4.0.0: version "4.0.2" @@ -14995,10 +14988,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" - integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== +webpack-dev-server@^3.11.2: + version "3.11.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" + integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -15020,11 +15013,11 @@ webpack-dev-server@^3.11.0: p-retry "^3.0.1" portfinder "^1.0.26" schema-utils "^1.0.0" - selfsigned "^1.10.7" + selfsigned "^1.10.8" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.20" - sockjs-client "1.4.0" + sockjs "^0.3.21" + sockjs-client "^1.5.0" spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" @@ -15092,14 +15085,7 @@ webpack@^4.46.0: watchpack "^1.7.4" webpack-sources "^1.4.1" -websocket-driver@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" - integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= - dependencies: - websocket-extensions ">=0.1.1" - -websocket-driver@>=0.5.1: +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== From 4219f3c907f5a609f6ba5bb49b50dc80a97bbe57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 09:29:00 -0400 Subject: [PATCH 18/33] Bump @types/react-virtualized-auto-sizer from 1.0.0 to 1.0.1 (#3649) Bumps [@types/react-virtualized-auto-sizer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-virtualized-auto-sizer) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-virtualized-auto-sizer) --- updated-dependencies: - dependency-name: "@types/react-virtualized-auto-sizer" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a0b4b11afe..64f940dc77 100644 --- a/package.json +++ b/package.json @@ -297,7 +297,7 @@ "@types/react-router-dom": "^5.1.6", "@types/react-select": "3.1.2", "@types/react-table": "^7.7.0", - "@types/react-virtualized-auto-sizer": "^1.0.0", + "@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-window": "^1.8.2", "@types/readable-stream": "^2.3.9", "@types/request": "^2.48.7", diff --git a/yarn.lock b/yarn.lock index 3de229cfae..4bb51fdadd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1853,10 +1853,10 @@ dependencies: "@types/react" "*" -"@types/react-virtualized-auto-sizer@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.0.tgz#fc32f30a8dab527b5816f3a757e1e1d040c8f272" - integrity sha512-NMErdIdSnm2j/7IqMteRiRvRulpjoELnXWUwdbucYCz84xG9PHcoOrr7QfXwB/ku7wd6egiKFrzt/+QK4Imeeg== +"@types/react-virtualized-auto-sizer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4" + integrity sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong== dependencies: "@types/react" "*" From 54ac31193327151270aff678ab63fb74dcef0bc2 Mon Sep 17 00:00:00 2001 From: chh <1474479+chenhunghan@users.noreply.github.com> Date: Tue, 24 Aug 2021 10:05:08 +0300 Subject: [PATCH 19/33] Add WelcomeBanner.width extension API (#3663) * Allow to add WelcomeBannerRegistration.width and use that to caculate to width of Banner container Signed-off-by: Hung-Han (Henry) Chen * Export at const Signed-off-by: Hung-Han (Henry) Chen --- .../registries/welcome-banner-registry.ts | 4 ++ .../+welcome/__test__/welcome.test.tsx | 27 ++++++++++++ src/renderer/components/+welcome/welcome.scss | 5 --- src/renderer/components/+welcome/welcome.tsx | 42 +++++++++++++------ 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/extensions/registries/welcome-banner-registry.ts b/src/extensions/registries/welcome-banner-registry.ts index ef36da8444..1102dc8a3f 100644 --- a/src/extensions/registries/welcome-banner-registry.ts +++ b/src/extensions/registries/welcome-banner-registry.ts @@ -30,6 +30,10 @@ export interface WelcomeBannerRegistration { * The banner component to be shown on the welcome screen. */ Banner?: React.ComponentType + /** + * The banner width in px. + */ + width?: number } export class WelcomeBannerRegistry extends BaseRegistry { } diff --git a/src/renderer/components/+welcome/__test__/welcome.test.tsx b/src/renderer/components/+welcome/__test__/welcome.test.tsx index 52f579643f..6eab098d05 100644 --- a/src/renderer/components/+welcome/__test__/welcome.test.tsx +++ b/src/renderer/components/+welcome/__test__/welcome.test.tsx @@ -24,6 +24,7 @@ import { render, screen } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; import { Welcome } from "../welcome"; import { TopBarRegistry, WelcomeMenuRegistry, WelcomeBannerRegistry } from "../../../../extensions/registries"; +import { defaultWidth } from "../welcome"; describe("", () => { beforeEach(() => { @@ -69,4 +70,30 @@ describe("", () => { expect(screen.queryByTestId(testId)).toBeInTheDocument(); expect(container.getElementsByClassName("logo").length).toBe(0); }); + + it("calculates max width from WelcomeBanner.width registered in WelcomeBannerRegistry", async () => { + WelcomeBannerRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ + { + width: 100, + Banner: () =>
+ }, + { + width: 800, + Banner: () =>
+ } + ]); + + render(); + + expect(screen.queryByTestId("welcome-banner-container")).toHaveStyle({ + // should take the max width of the banners (if > defaultWidth) + width: `800px`, + }); + expect(screen.queryByTestId("welcome-text-container")).toHaveStyle({ + width: `${defaultWidth}px` + }); + expect(screen.queryByTestId("welcome-menu-container")).toHaveStyle({ + width: `${defaultWidth}px` + }); + }); }); diff --git a/src/renderer/components/+welcome/welcome.scss b/src/renderer/components/+welcome/welcome.scss index bb1318c64e..94bf713192 100644 --- a/src/renderer/components/+welcome/welcome.scss +++ b/src/renderer/components/+welcome/welcome.scss @@ -25,10 +25,6 @@ height: 100%; z-index: 1; - .box { - width: 320px; - } - h2 { color: var(--textColorAccent); font-weight: 600; @@ -41,7 +37,6 @@ } ul { - width: 200px; margin-top: 20px; li { diff --git a/src/renderer/components/+welcome/welcome.tsx b/src/renderer/components/+welcome/welcome.tsx index ffb290fb09..d2ec4fea8c 100644 --- a/src/renderer/components/+welcome/welcome.tsx +++ b/src/renderer/components/+welcome/welcome.tsx @@ -29,21 +29,35 @@ import { WelcomeMenuRegistry } from "../../../extensions/registries"; import { WelcomeTopbar } from "../cluster-manager/welcome-topbar"; import { WelcomeBannerRegistry } from "../../../extensions/registries"; +export const defaultWidth = 320; + @observer export class Welcome extends React.Component { render() { const welcomeBanner = WelcomeBannerRegistry.getInstance().getItems(); + // if there is banner with specified width, use it to calculate the width of the container + const maxWidth = welcomeBanner.reduce((acc, curr) => { + const currWidth = curr.width ?? 0; + + if (acc > currWidth) { + return acc; + } + + return currWidth; + }, defaultWidth); + return ( <>
-
+
{welcomeBanner.length > 0 ? ( 1} autoPlay={true} + navButtonsAlwaysInvisible={true} > {welcomeBanner.map((item, index) => @@ -51,21 +65,25 @@ export class Welcome extends React.Component { ) : } -

Welcome to {productName} 5!

+
+
+

Welcome to {productName} 5!

-

+

To get you started we have auto-detected your clusters in your kubeconfig file and added them to the catalog, your centralized view for managing all your cloud-native resources. -

+

If you have any questions or feedback, please join our Lens Community slack channel. -

+

- + +
+
From 5f89b3e31fd111b20f041d7574a55647394d7e9b Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 24 Aug 2021 08:29:36 -0400 Subject: [PATCH 20/33] Fix filtering deprecated charts (#3635) --- .../k8s-api/endpoints/helm-charts.api.ts | 15 +- src/common/logger.ts | 4 +- src/common/utils/sort-compare.ts | 34 ++- src/main/helm/__mocks__/helm-chart-manager.ts | 270 +++++++++--------- src/main/helm/__tests__/helm-service.test.ts | 56 +++- src/main/helm/helm-chart-manager.ts | 97 ++++--- src/main/helm/helm-repo-manager.ts | 8 +- src/main/helm/helm-service.ts | 93 +----- .../+apps-helm-charts/helm-chart-details.scss | 6 + .../+apps-helm-charts/helm-chart-details.tsx | 27 +- 10 files changed, 325 insertions(+), 285 deletions(-) diff --git a/src/common/k8s-api/endpoints/helm-charts.api.ts b/src/common/k8s-api/endpoints/helm-charts.api.ts index 82d486ac81..706fcdf7f9 100644 --- a/src/common/k8s-api/endpoints/helm-charts.api.ts +++ b/src/common/k8s-api/endpoints/helm-charts.api.ts @@ -26,8 +26,7 @@ import type { RequestInit } from "node-fetch"; import { autoBind, bifurcateArray } from "../../utils"; import Joi from "joi"; -export type RepoHelmChartList = Record; -export type HelmChartList = Record; +export type RepoHelmChartList = Record; export interface IHelmChartDetails { readme: string; @@ -43,7 +42,7 @@ const endpoint = compile(`/v2/charts/:repo?/:name?`) as (params?: { * Get a list of all helm charts from all saved helm repos */ export async function listCharts(): Promise { - const data = await apiBase.get(endpoint()); + const data = await apiBase.get>(endpoint()); return Object .values(data) @@ -311,11 +310,9 @@ export class HelmChart { } static create(data: RawHelmChart, { onError = "throw" }: HelmChartCreateOpts = {}): HelmChart | undefined { - const result = helmChartValidator.validate(data, { + const { value, error } = helmChartValidator.validate(data, { abortEarly: false, }); - let { error } = result; - const { value } = result; if (!error) { return new HelmChart(value); @@ -331,13 +328,13 @@ export class HelmChart { return new HelmChart(value); } - error = new Joi.ValidationError(actualErrors.map(er => er.message).join(". "), actualErrors, error._original); + const validationError = new Joi.ValidationError(actualErrors.map(er => er.message).join(". "), actualErrors, error._original); if (onError === "throw") { - throw error; + throw validationError; } - console.warn("[HELM-CHART]: failed to validate data", data, error); + console.warn("[HELM-CHART]: failed to validate data", data, validationError); return undefined; } diff --git a/src/common/logger.ts b/src/common/logger.ts index 723d43f70c..826b576614 100644 --- a/src/common/logger.ts +++ b/src/common/logger.ts @@ -31,7 +31,9 @@ const logLevel = process.env.LOG_LEVEL ? process.env.LOG_LEVEL : isDebugging ? "debug" - : "info"; + : isTestEnv + ? "error" + : "info"; const transports: Transport[] = [ new SentryTransport("error") diff --git a/src/common/utils/sort-compare.ts b/src/common/utils/sort-compare.ts index cd4e1b128a..041a239bb5 100644 --- a/src/common/utils/sort-compare.ts +++ b/src/common/utils/sort-compare.ts @@ -19,7 +19,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import semver, { SemVer } from "semver"; +import semver, { coerce, SemVer } from "semver"; +import * as iter from "./iter"; +import type { RawHelmChart } from "../k8s-api/endpoints/helm-charts.api"; +import logger from "../logger"; export function sortCompare(left: T, right: T): -1 | 0 | 1 { if (left < right) { @@ -53,3 +56,32 @@ export function sortCompareChartVersions(left: ChartVersion, right: ChartVersion return sortCompare(left.version, right.version); } + + + +export function sortCharts(charts: RawHelmChart[]) { + interface ExtendedHelmChart extends RawHelmChart { + __version: SemVer; + } + + const chartsWithVersion = Array.from( + iter.map( + charts, + (chart => { + const __version = coerce(chart.version, { includePrerelease: true, loose: true }); + + if (!__version) { + logger.warn(`[HELM-SERVICE]: Version from helm chart is not loosely coercable to semver.`, { name: chart.name, version: chart.version, repo: chart.repo }); + } + + (chart as ExtendedHelmChart).__version = __version; + + return chart as ExtendedHelmChart; + }) + ), + ); + + return chartsWithVersion + .sort(sortCompareChartVersions) + .map(chart => (delete chart.__version, chart)); +} diff --git a/src/main/helm/__mocks__/helm-chart-manager.ts b/src/main/helm/__mocks__/helm-chart-manager.ts index 6a511273da..09f071f842 100644 --- a/src/main/helm/__mocks__/helm-chart-manager.ts +++ b/src/main/helm/__mocks__/helm-chart-manager.ts @@ -19,141 +19,151 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { HelmRepo, HelmRepoManager } from "../helm-repo-manager"; +import { sortCharts } from "../../../common/utils"; +import type { HelmRepo } from "../helm-repo-manager"; + +const charts = new Map([ + ["stable", { + "invalid-semver": sortCharts([ + { + apiVersion: "3.0.0", + name: "weird-versioning", + version: "I am not semver", + repo: "stable", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "weird-versioning", + version: "v4.3.0", + repo: "stable", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "weird-versioning", + version: "I am not semver but more", + repo: "stable", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "weird-versioning", + version: "v4.4.0", + repo: "stable", + digest: "test", + created: "now", + }, + ]), + "apm-server": sortCharts([ + { + apiVersion: "3.0.0", + name: "apm-server", + version: "2.1.7", + repo: "stable", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "apm-server", + version: "2.1.6", + repo: "stable", + digest: "test", + created: "now", + } + ]), + "redis": sortCharts([ + { + apiVersion: "3.0.0", + name: "apm-server", + version: "1.0.0", + repo: "stable", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "apm-server", + version: "0.0.9", + repo: "stable", + digest: "test", + created: "now", + } + ]), + }], + ["experiment", { + "fairwind": sortCharts([ + { + apiVersion: "3.0.0", + name: "fairwind", + version: "0.0.1", + repo: "experiment", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "fairwind", + version: "0.0.2", + repo: "experiment", + digest: "test", + deprecated: true, + created: "now", + } + ]), + }], + ["bitnami", { + "hotdog": sortCharts([ + { + apiVersion: "3.0.0", + name: "hotdog", + version: "1.0.1", + repo: "bitnami", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "hotdog", + version: "1.0.2", + repo: "bitnami", + digest: "test", + created: "now", + } + ]), + "pretzel": sortCharts([ + { + apiVersion: "3.0.0", + name: "pretzel", + version: "1.0", + repo: "bitnami", + digest: "test", + created: "now", + }, + { + apiVersion: "3.0.0", + name: "pretzel", + version: "1.0.1", + repo: "bitnami", + digest: "test", + created: "now", + } + ]), + }], +]); export class HelmChartManager { - cache: any = {}; - private repo: HelmRepo; + constructor(private repo: HelmRepo){ } - constructor(repo: HelmRepo){ - this.cache = HelmRepoManager.cache; - this.repo = repo; + static forRepo(repo: HelmRepo) { + return new this(repo); } public async charts(): Promise { - switch (this.repo.name) { - case "stable": - return Promise.resolve({ - "invalid-semver": [ - { - apiVersion: "3.0.0", - name: "weird-versioning", - version: "I am not semver", - repo: "stable", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "weird-versioning", - version: "v4.3.0", - repo: "stable", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "weird-versioning", - version: "I am not semver but more", - repo: "stable", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "weird-versioning", - version: "v4.4.0", - repo: "stable", - digest: "test" - }, - ], - "apm-server": [ - { - apiVersion: "3.0.0", - name: "apm-server", - version: "2.1.7", - repo: "stable", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "apm-server", - version: "2.1.6", - repo: "stable", - digest: "test" - } - ], - "redis": [ - { - apiVersion: "3.0.0", - name: "apm-server", - version: "1.0.0", - repo: "stable", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "apm-server", - version: "0.0.9", - repo: "stable", - digest: "test" - } - ] - }); - case "experiment": - return Promise.resolve({ - "fairwind": [ - { - apiVersion: "3.0.0", - name: "fairwind", - version: "0.0.1", - repo: "experiment", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "fairwind", - version: "0.0.2", - repo: "experiment", - digest: "test", - deprecated: true - } - ] - }); - case "bitnami": - return Promise.resolve({ - "hotdog": [ - { - apiVersion: "3.0.0", - name: "hotdog", - version: "1.0.1", - repo: "bitnami", - digest: "test" - }, - { - apiVersion: "3.0.0", - name: "hotdog", - version: "1.0.2", - repo: "bitnami", - digest: "test", - } - ], - "pretzel": [ - { - apiVersion: "3.0.0", - name: "pretzel", - version: "1.0", - repo: "bitnami", - digest: "test", - }, - { - apiVersion: "3.0.0", - name: "pretzel", - version: "1.0.1", - repo: "bitnami", - digest: "test" - } - ] - }); - default: - return Promise.resolve({}); - } + return charts.get(this.repo.name) ?? {}; } } diff --git a/src/main/helm/__tests__/helm-service.test.ts b/src/main/helm/__tests__/helm-service.test.ts index 56127c1684..7eaf865464 100644 --- a/src/main/helm/__tests__/helm-service.test.ts +++ b/src/main/helm/__tests__/helm-service.test.ts @@ -31,7 +31,7 @@ describe("Helm Service tests", () => { jest.resetAllMocks(); }); - it("list charts without deprecated ones", async () => { + it("list charts with deprecated entries", async () => { mockHelmRepoManager.mockReturnValue({ init: jest.fn(), repositories: jest.fn().mockImplementation(async () => { @@ -52,14 +52,16 @@ describe("Helm Service tests", () => { name: "apm-server", version: "2.1.7", repo: "stable", - digest: "test" + digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "apm-server", version: "2.1.6", repo: "stable", - digest: "test" + digest: "test", + created: "now", } ], "invalid-semver": [ @@ -68,28 +70,32 @@ describe("Helm Service tests", () => { name: "weird-versioning", version: "v4.4.0", repo: "stable", - digest: "test" + digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "weird-versioning", version: "v4.3.0", repo: "stable", - digest: "test" + digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "weird-versioning", version: "I am not semver", repo: "stable", - digest: "test" + digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "weird-versioning", version: "I am not semver but more", repo: "stable", - digest: "test" + digest: "test", + created: "now", }, ], "redis": [ @@ -98,18 +104,40 @@ describe("Helm Service tests", () => { name: "apm-server", version: "1.0.0", repo: "stable", - digest: "test" + digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "apm-server", version: "0.0.9", repo: "stable", - digest: "test" + digest: "test", + created: "now", } ] }, - experiment: {} + experiment: { + "fairwind": [ + { + apiVersion: "3.0.0", + name: "fairwind", + version: "0.0.2", + repo: "experiment", + digest: "test", + deprecated: true, + created: "now", + }, + { + apiVersion: "3.0.0", + name: "fairwind", + version: "0.0.1", + repo: "experiment", + digest: "test", + created: "now", + }, + ] + } }); }); @@ -134,13 +162,15 @@ describe("Helm Service tests", () => { version: "1.0.2", repo: "bitnami", digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "hotdog", version: "1.0.1", repo: "bitnami", - digest: "test" + digest: "test", + created: "now", }, ], "pretzel": [ @@ -150,13 +180,15 @@ describe("Helm Service tests", () => { version: "1.0.1", repo: "bitnami", digest: "test", + created: "now", }, { apiVersion: "3.0.0", name: "pretzel", version: "1.0", repo: "bitnami", - digest: "test" + digest: "test", + created: "now", } ] } diff --git a/src/main/helm/helm-chart-manager.ts b/src/main/helm/helm-chart-manager.ts index 5523e0f050..b8261845db 100644 --- a/src/main/helm/helm-chart-manager.ts +++ b/src/main/helm/helm-chart-manager.ts @@ -20,27 +20,25 @@ */ import fs from "fs"; +import v8 from "v8"; import * as yaml from "js-yaml"; -import { HelmRepo, HelmRepoManager } from "./helm-repo-manager"; +import type { HelmRepo } from "./helm-repo-manager"; import logger from "../logger"; import { promiseExec } from "../promise-exec"; import { helmCli } from "./helm-cli"; import type { RepoHelmChartList } from "../../common/k8s-api/endpoints/helm-charts.api"; - -type CachedYaml = { - entries: RepoHelmChartList -}; +import { sortCharts } from "../../common/utils"; export class HelmChartManager { - protected cache: any = {}; - protected repo: HelmRepo; + static #cache = new Map(); - constructor(repo: HelmRepo){ - this.cache = HelmRepoManager.cache; - this.repo = repo; + private constructor(protected repo: HelmRepo) {} + + static forRepo(repo: HelmRepo) { + return new this(repo); } - public async chart(name: string) { + public async chartVersions(name: string) { const charts = await this.charts(); return charts[name]; @@ -48,9 +46,7 @@ export class HelmChartManager { public async charts(): Promise { try { - const cachedYaml = await this.cachedYaml(); - - return cachedYaml["entries"]; + return await this.cachedYaml(); } catch(error) { logger.error("HELM-CHART-MANAGER]: failed to list charts", { error }); @@ -58,48 +54,61 @@ export class HelmChartManager { } } - public async getReadme(name: string, version = "") { + private async executeCommand(action: string, name: string, version?: string) { const helm = await helmCli.binaryPath(); + const cmd = [`"${helm}" ${action} ${this.repo.name}/${name}`]; - if(version && version != "") { - const { stdout } = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);}); - - return stdout; - } else { - const { stdout } = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);}); + if (version) { + cmd.push("--version", version); + } + + try { + const { stdout } = await promiseExec(cmd.join(" ")); return stdout; + } catch (error) { + throw error.stderr || error; } } - public async getValues(name: string, version = "") { - const helm = await helmCli.binaryPath(); - - if(version && version != "") { - const { stdout } = await promiseExec(`"${helm}" show values ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);}); - - return stdout; - } else { - const { stdout } = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);}); - - return stdout; - } + public async getReadme(name: string, version?: string) { + return this.executeCommand("show readme", name, version); } - protected async cachedYaml(): Promise { - if (!(this.repo.name in this.cache)) { + public async getValues(name: string, version?: string) { + return this.executeCommand("show values", name, version); + } + + protected async cachedYaml(): Promise { + if (!HelmChartManager.#cache.has(this.repo.name)) { const cacheFile = await fs.promises.readFile(this.repo.cacheFilePath, "utf-8"); - const data = yaml.safeLoad(cacheFile); + const { entries } = yaml.safeLoad(cacheFile) as { entries: RepoHelmChartList }; - for(const key in data["entries"]) { - data["entries"][key].forEach((version: any) => { - version["repo"] = this.repo.name; - version["created"] = Date.parse(version.created).toString(); - }); - } - this.cache[this.repo.name] = Buffer.from(JSON.stringify(data)); + /** + * Do some initial preprocessing on the data, so as to avoid needing to do it later + * 1. Set the repo name + * 2. Normalize the created date + * 3. Filter out deprecated items + */ + + const normalized = Object.fromEntries( + Object.entries(entries) + .map(([name, charts]) => [ + name, + sortCharts( + charts.map(chart => ({ + ...chart, + created: Date.parse(chart.created).toString(), + repo: this.repo.name, + })), + ), + ] as const) + .filter(([, charts]) => !charts.every(chart => chart.deprecated)) + ); + + HelmChartManager.#cache.set(this.repo.name, v8.serialize(normalized)); } - return JSON.parse(this.cache[this.repo.name].toString()); + return v8.deserialize(HelmChartManager.#cache.get(this.repo.name)); } } diff --git a/src/main/helm/helm-repo-manager.ts b/src/main/helm/helm-repo-manager.ts index d1c904539d..9e4038a10f 100644 --- a/src/main/helm/helm-repo-manager.ts +++ b/src/main/helm/helm-repo-manager.ts @@ -50,8 +50,6 @@ export interface HelmRepo { } export class HelmRepoManager extends Singleton { - static cache = {}; // todo: remove implicit updates in helm-chart-manager.ts - protected repos: HelmRepo[]; protected helmEnv: HelmEnv; protected initialized: boolean; @@ -97,6 +95,12 @@ export class HelmRepoManager extends Singleton { return env; } + public async repo(name: string): Promise { + const repos = await this.repositories(); + + return repos.find(repo => repo.name === name); + } + public async repositories(): Promise { try { if (!this.initialized) { diff --git a/src/main/helm/helm-service.ts b/src/main/helm/helm-service.ts index 2fe531c215..41c8438cb3 100644 --- a/src/main/helm/helm-service.ts +++ b/src/main/helm/helm-service.ts @@ -19,14 +19,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import semver, { SemVer } from "semver"; import type { Cluster } from "../cluster"; import logger from "../logger"; import { HelmRepoManager } from "./helm-repo-manager"; import { HelmChartManager } from "./helm-chart-manager"; -import type { HelmChart, HelmChartList, RepoHelmChartList } from "../../common/k8s-api/endpoints/helm-charts.api"; import { deleteRelease, getHistory, getRelease, getValues, installChart, listReleases, rollback, upgradeRelease } from "./helm-release-manager"; -import { iter, sortCompareChartVersions } from "../../common/utils"; interface GetReleaseValuesArgs { cluster: Cluster; @@ -42,43 +39,27 @@ class HelmService { } public async listCharts() { - const charts: HelmChartList = {}; const repositories = await HelmRepoManager.getInstance().repositories(); - for (const repo of repositories) { - charts[repo.name] = {}; - const manager = new HelmChartManager(repo); - const sortedCharts = this.sortChartsByVersion(await manager.charts()); - const enabledCharts = this.excludeDeprecatedChartGroups(sortedCharts); - - charts[repo.name] = enabledCharts; - } - - return charts; + return Object.fromEntries( + await Promise.all(repositories.map(async repo => [repo.name, await HelmChartManager.forRepo(repo).charts()])) + ); } public async getChart(repoName: string, chartName: string, version = "") { - const result = { - readme: "", - versions: {} + const repo = await HelmRepoManager.getInstance().repo(repoName); + const chartManager = HelmChartManager.forRepo(repo); + + return { + readme: await chartManager.getReadme(chartName, version), + versions: await chartManager.chartVersions(chartName), }; - const repos = await HelmRepoManager.getInstance().repositories(); - const repo = repos.find(repo => repo.name === 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 repos = await HelmRepoManager.getInstance().repositories(); - const repo = repos.find(repo => repo.name === repoName); - const chartManager = new HelmChartManager(repo); + const repo = await HelmRepoManager.getInstance().repo(repoName); - return chartManager.getValues(chartName, version); + return HelmChartManager.forRepo(repo).getValues(chartName, version); } public async listReleases(cluster: Cluster, namespace: string = null) { @@ -131,58 +112,6 @@ class HelmService { return { message: output }; } - - private excludeDeprecatedChartGroups(chartGroups: RepoHelmChartList) { - return Object.fromEntries( - iter.filterMap( - Object.entries(chartGroups), - ([name, charts]) => { - for (const chart of charts) { - if (chart.deprecated) { - // ignore chart group if any chart is deprecated - return undefined; - } - } - - return [name, charts]; - } - ) - ); - } - - private sortCharts(charts: HelmChart[]) { - interface ExtendedHelmChart extends HelmChart { - __version: SemVer; - } - - const chartsWithVersion = Array.from( - iter.map( - charts, - (chart => { - const __version = semver.coerce(chart.version, { includePrerelease: true, loose: true }); - - if (!__version) { - logger.error(`[HELM-SERVICE]: Version from helm chart is not loosely coercable to semver.`, { name: chart.name, version: chart.version, repo: chart.repo }); - } - - (chart as ExtendedHelmChart).__version = __version; - - return chart as ExtendedHelmChart; - }) - ), - ); - - return chartsWithVersion - .sort(sortCompareChartVersions) - .map(chart => (delete chart.__version, chart as HelmChart)); - } - - private sortChartsByVersion(chartGroups: RepoHelmChartList) { - return Object.fromEntries( - Object.entries(chartGroups) - .map(([name, charts]) => [name, this.sortCharts(charts)]) - ); - } } export const helmService = new HelmService(); diff --git a/src/renderer/components/+apps-helm-charts/helm-chart-details.scss b/src/renderer/components/+apps-helm-charts/helm-chart-details.scss index 13521ce583..7bee3b7f10 100644 --- a/src/renderer/components/+apps-helm-charts/helm-chart-details.scss +++ b/src/renderer/components/+apps-helm-charts/helm-chart-details.scss @@ -30,6 +30,12 @@ box-sizing: content-box; } + .Select__option { + span.deprecated { + text-decoration: line-through; + } + } + .intro-contents { .description { font-weight: bold; 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 1cedc10d3f..041f7b1cbd 100644 --- a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx +++ b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx @@ -33,12 +33,19 @@ import { Button } from "../button"; import { Select, SelectOption } from "../select"; import { createInstallChartTab } from "../dock/install-chart.store"; import { Badge } from "../badge"; +import { Tooltip, withStyles } from "@material-ui/core"; interface Props { chart: HelmChart; hideDetails(): void; } +const LargeTooltip = withStyles({ + tooltip: { + fontSize: "var(--font-size-small)", + } +})(Tooltip); + @observer export class HelmChartDetails extends Component { @observable chartVersions: HelmChart[]; @@ -73,15 +80,15 @@ export class HelmChartDetails extends Component { }); @boundMethod - async onVersionChange({ value: version }: SelectOption) { - this.selectedChart = this.chartVersions.find(chart => chart.version === version); + async onVersionChange({ value: chart }: SelectOption) { + this.selectedChart = chart; this.readme = null; try { this.abortController?.abort(); this.abortController = new AbortController(); const { chart: { name, repo } } = this.props; - const { readme } = await getChartDetails(repo, name, { version, reqInit: { signal: this.abortController.signal }}); + const { readme } = await getChartDetails(repo, name, { version: chart.version, reqInit: { signal: this.abortController.signal }}); this.readme = readme; } catch (error) { @@ -115,7 +122,19 @@ export class HelmChartDetails extends Component {