diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 6bb07489ec..a4108e6762 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -1,19 +1,7 @@ variables: YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn -pr: - branches: - include: - - master - - releases/* - paths: - exclude: - - .github/* - - docs/* - - mkdocs/* +pr: none trigger: - branches: - include: - - '*' tags: include: - "*" @@ -57,11 +45,6 @@ jobs: displayName: Run tests - script: make test-extensions displayName: Run In-tree Extension tests - - bash: | - rm -rf extensions/telemetry - make integration-win - git checkout extensions/telemetry - displayName: Run integration tests - script: make build condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))" displayName: Build @@ -69,6 +52,8 @@ jobs: WIN_CSC_LINK: $(WIN_CSC_LINK) WIN_CSC_KEY_PASSWORD: $(WIN_CSC_KEY_PASSWORD) GH_TOKEN: $(GH_TOKEN) + AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) - job: macOS pool: vmImage: macOS-10.14 @@ -101,13 +86,6 @@ jobs: displayName: Run tests - script: make test-extensions displayName: Run In-tree Extension tests - - bash: | - rm -rf extensions/telemetry - make integration-mac - git checkout extensions/telemetry - displayName: Run integration tests - - script: make test-extensions - displayName: Run In-tree Extension tests - script: make build condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))" displayName: Build @@ -117,6 +95,8 @@ jobs: CSC_LINK: $(CSC_LINK) CSC_KEY_PASSWORD: $(CSC_KEY_PASSWORD) GH_TOKEN: $(GH_TOKEN) + AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) - job: Linux pool: vmImage: ubuntu-16.04 @@ -149,20 +129,6 @@ jobs: displayName: Run tests - script: make test-extensions displayName: Run In-tree Extension tests - - bash: | - sudo apt-get update - sudo apt-get install libgconf-2-4 conntrack -y - curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 - sudo install minikube-linux-amd64 /usr/local/bin/minikube - sudo minikube start --driver=none - # Although the kube and minikube config files are in placed $HOME they are owned by root - sudo chown -R $USER $HOME/.kube $HOME/.minikube - displayName: Install integration test dependencies - - bash: | - rm -rf extensions/telemetry - xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' make integration-linux - git checkout extensions/telemetry - displayName: Run integration tests - bash: | sudo chown root:root / sudo apt-get update && sudo apt-get install -y snapd @@ -178,6 +144,8 @@ jobs: condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))" env: GH_TOKEN: $(GH_TOKEN) + AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) - script: make publish-npm displayName: Publish npm package condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))" diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 0000000000..a77a36c653 --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,17 @@ +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates +# for config options + +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 4 + reviewers: + - "lensapp/lens-maintainers" + labels: + - "dependencies" + versioning-strategy: + lockfile-only: false + increase: true diff --git a/.eslintrc.js b/.eslintrc.js index 3fd52c2465..57ee07348f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -46,6 +46,8 @@ module.exports = { "avoidEscape": true, "allowTemplateLiterals": true, }], + "linebreak-style": ["error", "unix"], + "eol-last": ["error", "always"], "semi": ["error", "always"], "object-shorthand": "error", "prefer-template": "error", @@ -101,6 +103,8 @@ module.exports = { }], "semi": "off", "@typescript-eslint/semi": ["error"], + "linebreak-style": ["error", "unix"], + "eol-last": ["error", "always"], "object-shorthand": "error", "prefer-template": "error", "template-curly-spacing": "error", @@ -162,6 +166,8 @@ module.exports = { }], "semi": "off", "@typescript-eslint/semi": ["error"], + "linebreak-style": ["error", "unix"], + "eol-last": ["error", "always"], "object-shorthand": "error", "prefer-template": "error", "template-curly-spacing": "error", diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..fccf0482de --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# This is the default code owners for the whole Lens repo +* @lensapp/lens-ide diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000000..02ae36727e --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,30 @@ +exclude-labels: + - 'skip-changelog' +categories: + - title: '🚀 Features' + labels: + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'bug' + - title: '🧰 Maintenance' + labels: + - 'chore' + - 'area/ci' + - 'area/tests' + - 'dependencies' + +template: | + ## Changes since $PREVIOUS_TAG + + $CHANGES + + ### Download + + - Lens v$RESOLVED_VERSION - Linux + - [AppImage](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.x86_64.AppImage) + - [DEB](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.amd64.deb) + - [RPM](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.x86_64.rpm) + - [Snapcraft](https://snapcraft.io/kontena-lens) + - [Lens v$RESOLVED_VERSION - MacOS](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.dmg) + - [Lens v$RESOLVED_VERSION - Windows](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-Setup-$RESOLVED_VERSION.exe) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0c6340d6a2..afbcc74367 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: uses: actions/setup-python@v2 with: python-version: '3.x' - + - name: Checkout Release from lens uses: actions/checkout@v2 with: @@ -83,12 +83,12 @@ jobs: mike deploy --push master - name: Get the release version - if: contains(github.ref, 'refs/tags/v') # && !github.event.release.prerelease (generate pre-release docs until Lens 4.0.0 is GA, see #1408) + if: contains(github.ref, 'refs/tags/v') && !github.event.release.prerelease id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - name: mkdocs deploy new release - if: contains(github.ref, 'refs/tags/v') # && !github.event.release.prerelease (generate pre-release docs until Lens 4.0.0 is GA, see #1408) + if: contains(github.ref, 'refs/tags/v') && !github.event.release.prerelease run: | mike deploy --push --update-aliases ${{ steps.get_version.outputs.VERSION }} latest mike set-default --push ${{ steps.get_version.outputs.VERSION }} diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml new file mode 100644 index 0000000000..dfa16b99c7 --- /dev/null +++ b/.github/workflows/maintenance.yml @@ -0,0 +1,22 @@ +name: "Maintenance" +on: + # So that PRs touching the same files as the push are updated + push: + # So that the `dirtyLabel` is removed if conflicts are resolve + # We recommend `pull_request_target` so that github secrets are available. + # In `pull_request` we wouldn't be able to change labels of fork PRs + pull_request_target: + types: [synchronize] + +jobs: + main: + runs-on: ubuntu-latest + steps: + - name: check if prs are dirty + uses: eps1lon/actions-label-merge-conflict@releases/2.x + with: + dirtyLabel: "PR: needs rebase" + removeOnDirtyLabel: "PR: ready to ship" + repoToken: "${{ secrets.GITHUB_TOKEN }}" + commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request." + commentOnClean: "Conflicts have been resolved. A maintainer will review the pull request shortly." diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000000..ec49fec6e5 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,16 @@ +name: Release Drafter + +on: + push: + # branches to consider in the event; optional, defaults to all + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000..d7f3959eb8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,83 @@ +name: Test +on: + - pull_request +jobs: + build: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-16.04, macos-10.15, windows-2019] + node-version: [12.x] + steps: + - name: Checkout Release from lens + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Using Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v2 + id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - run: make node_modules + name: Install dependencies + + - run: make build-npm + name: Generate npm package + + - run: make -j2 build-extensions + name: Build bundled extensions + + - run: make test + name: Run tests + + - run: make test-extensions + name: Run In-tree Extension tests + + - run: | + sudo apt-get update + sudo apt-get install libgconf-2-4 conntrack -y + curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 + sudo install minikube-linux-amd64 /usr/local/bin/minikube + sudo minikube start --driver=none + # Although the kube and minikube config files are in placed $HOME they are owned by root + sudo chown -R $USER $HOME/.kube $HOME/.minikube + name: Install integration test dependencies + if: runner.os == 'Linux' + - run: | + set -e + rm -rf extensions/telemetry + xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' make integration-linux + git checkout extensions/telemetry + name: Run Linux integration tests + if: runner.os == 'Linux' + + - run: | + set -e + rm -rf extensions/telemetry + make integration-win + git checkout extensions/telemetry + name: Run Windows integration tests + shell: bash + if: runner.os == 'Windows' + + - run: | + set -e + rm -rf extensions/telemetry + make integration-mac + git checkout extensions/telemetry + name: Run macOS integration tests + if: runner.os == 'macOS' diff --git a/.gitignore b/.gitignore index 88d48ab5ee..d018f3b251 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,3 @@ types/extension-renderer-api.d.ts extensions/*/dist docs/extensions/api site/ -.vscode/ diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..7d7cef13d8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,57 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Main Process", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}", + "protocol": "inspector", + "preLaunchTask": "compile-dev", + "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron", + "windows": { + "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd" + }, + "runtimeArgs": [ + "--remote-debugging-port=9223", + "--inspect", + "." + ], + "outputCapture": "std" + }, + { + "name": "Renderer Process", + "type": "pwa-chrome", + "request": "attach", + "port": 9223, + "webRoot": "${workspaceFolder}", + "timeout": 30000 + }, + { + "name": "Integration Tests", + "type": "node", + "request": "launch", + "console": "integratedTerminal", + "runtimeArgs": [ + "${workspaceFolder}/node_modules/.bin/jest", + "--runInBand", + "integration" + ], + }, + { + "name": "Unit Tests", + "type": "node", + "request": "launch", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/jest/bin/jest.js", + "args": [ + "--env=jsdom", + "-i", + "src" + ] + } + ], +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..03a7b306f7 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,18 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "group": "build", + "command": "yarn", + "args": [ + "debug-build" + ], + "problemMatcher": [], + "label": "compile-dev", + "detail": "Compiles main and extension types" + } + ] +} \ No newline at end of file diff --git a/.yarnrc b/.yarnrc index 5119ded102..f11de8a2a9 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "9.1.0" +target "9.4.4" runtime "electron" diff --git a/LICENSE b/LICENSE index b7a6d74205..37da2d2e07 100644 --- a/LICENSE +++ b/LICENSE @@ -1,12 +1,12 @@ -Copyright (c) 2020 Mirantis, Inc. +Copyright (c) 2021 Mirantis, Inc. Portions of this software are licensed as follows: -* All content residing under the "docs/" directory of this repository, if that +* All content residing under the "docs/" directory of this repository, if that directory exists, is licensed under "Creative Commons: CC BY-SA 4.0 license". -* All third party components incorporated into the Lens Software are licensed +* All third party components incorporated into the Lens Software are licensed under the original license provided by the owner of the applicable component. -* Content outside of the above mentioned directories or restrictions above is +* Content outside of the above mentioned directories or restrictions above is available under the "MIT" license as defined below. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Makefile b/Makefile index 362ef3b830..658be09690 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,8 @@ +CMD_ARGS = $(filter-out $@,$(MAKECMDGOALS)) + +%: + @: + EXTENSIONS_DIR = ./extensions extensions = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir}) extension_node_modules = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir}/node_modules) @@ -9,23 +14,23 @@ else DETECTED_OS := $(shell uname) endif -binaries/client: +binaries/client: node_modules yarn download-bins -node_modules: +node_modules: yarn.lock yarn install --frozen-lockfile yarn check --verify-tree --integrity -static/build/LensDev.html: +static/build/LensDev.html: node_modules yarn compile:renderer .PHONY: compile-dev -compile-dev: +compile-dev: node_modules yarn compile:main --cache yarn compile:renderer --cache .PHONY: dev -dev: node_modules binaries/client build-extensions static/build/LensDev.html +dev: binaries/client build-extensions static/build/LensDev.html yarn dev .PHONY: lint @@ -34,27 +39,30 @@ lint: .PHONY: test test: binaries/client - yarn test + yarn run jest $(or $(CMD_ARGS), "src") .PHONY: integration-linux -integration-linux: build-extension-types build-extensions +integration-linux: binaries/client build-extension-types build-extensions +# ifdef XDF_CONFIG_HOME +# rm -rf ${XDG_CONFIG_HOME}/.config/Lens +# else +# rm -rf ${HOME}/.config/Lens +# endif yarn build:linux yarn integration .PHONY: integration-mac -integration-mac: build-extension-types build-extensions +integration-mac: binaries/client build-extension-types build-extensions + # rm ${HOME}/Library/Application\ Support/Lens yarn build:mac yarn integration .PHONY: integration-win -integration-win: build-extension-types build-extensions +integration-win: binaries/client build-extension-types build-extensions + # rm %APPDATA%/Lens yarn build:win yarn integration -.PHONY: test-app -test-app: - yarn test - .PHONY: build build: node_modules binaries/client build-extensions ifeq "$(DETECTED_OS)" "Windows" @@ -70,7 +78,7 @@ $(extension_dists): src/extensions/npm/extensions/dist cd $(@:/dist=) && npm run build .PHONY: build-extensions -build-extensions: $(extension_node_modules) $(extension_dists) +build-extensions: node_modules $(extension_node_modules) $(extension_dists) .PHONY: test-extensions test-extensions: $(extension_node_modules) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..b1a54ec9d0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Reporting a Vulnerability + +Team Lens encourages users who become aware of a security vulnerability in Lens to contact Team Lens with details of the vulnerability. Team Lens has established an email address that should be used for reporting a vulnerability. Please send descriptions of any vulnerabilities found to security@k8slens.dev. Please include details on the software and hardware configuration of your system so that we can duplicate the issue being reported. + +Team Lens hopes that users encountering a new vulnerability will contact us privately as it is in the best interests of our users that Team Lens has an opportunity to investigate and confirm a suspected vulnerability before it becomes public knowledge. + +In the case of vulnerabilities found in third-party software components used in Lens, please also notify Team Lens as described above. diff --git a/__mocks__/imageMock.ts b/__mocks__/imageMock.ts index a099545376..f053ebf797 100644 --- a/__mocks__/imageMock.ts +++ b/__mocks__/imageMock.ts @@ -1 +1 @@ -module.exports = {}; \ No newline at end of file +module.exports = {}; diff --git a/__mocks__/styleMock.ts b/__mocks__/styleMock.ts index a099545376..f053ebf797 100644 --- a/__mocks__/styleMock.ts +++ b/__mocks__/styleMock.ts @@ -1 +1 @@ -module.exports = {}; \ No newline at end of file +module.exports = {}; diff --git a/build/icons/512x512.png b/build/icons/512x512.png index 2c953f6efd..e08b9f5b15 100644 Binary files a/build/icons/512x512.png and b/build/icons/512x512.png differ diff --git a/build/icons/512x512@2x.png b/build/icons/512x512@2x.png new file mode 100644 index 0000000000..da0aa8ae80 Binary files /dev/null and b/build/icons/512x512@2x.png differ diff --git a/docs/clusters/adding-clusters.md b/docs/clusters/adding-clusters.md index d153d8c9bf..c9a533a700 100644 --- a/docs/clusters/adding-clusters.md +++ b/docs/clusters/adding-clusters.md @@ -2,7 +2,7 @@ Add clusters by clicking the **Add Cluster** button in the left-side menu. -1. Click the **Add Cluster** button (indicated with a '+' icon). +1. Click the **Add Cluster** button (indicated with a '+' icon). Or [click here](lens://app/cluster). 2. Enter the path to your kubeconfig file. You'll need to have a kubeconfig file for the cluster you want to add. You can either browse for the path from the file system or or enter it directly. Selected [cluster contexts](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context) are added as a separate item in the left-side cluster menu to allow you to operate easily on multiple clusters and/or contexts. diff --git a/docs/extensions/README.md b/docs/extensions/README.md index 7866b65497..f8906d75ee 100644 --- a/docs/extensions/README.md +++ b/docs/extensions/README.md @@ -1,6 +1,9 @@ # Lens Extension API -Customize and enhance the Lens experience with the Lens Extension API. Use the extension API to create menus or page content. The same extension API was used to create many of Lens's core features. +Customize and enhance the Lens experience with the Lens Extension API. +Use the extension API to create menus or page content. +The same extension API was used to create many of Lens's core features. +To install your first extension you should goto the [extension page](lens://app/extensions) in lens. This documentation describes: diff --git a/docs/extensions/capabilities/color-reference.md b/docs/extensions/capabilities/color-reference.md index 660e0fe067..6a38ba861c 100644 --- a/docs/extensions/capabilities/color-reference.md +++ b/docs/extensions/capabilities/color-reference.md @@ -43,6 +43,7 @@ You can use theme-based CSS Variables to style an extension according to the act ## Button Colors - `--buttonPrimaryBackground`: button background color for primary actions. - `--buttonDefaultBackground`: default button background color. +- `--buttonLightBackground`: light button background color. - `--buttonAccentBackground`: accent button background color. - `--buttonDisabledBackground`: disabled button background color. diff --git a/docs/extensions/capabilities/common-capabilities.md b/docs/extensions/capabilities/common-capabilities.md index 6fdb87db82..1410dfc148 100644 --- a/docs/extensions/capabilities/common-capabilities.md +++ b/docs/extensions/capabilities/common-capabilities.md @@ -40,7 +40,7 @@ This extension can register custom app menus that will be displayed on OS native Example: -``` typescript +```typescript import { LensMainExtension, windowManager } from "@k8slens/extensions" export default class ExampleMainExtension extends LensMainExtension { @@ -92,7 +92,7 @@ export default class ExampleMainExtension extends LensRendererExtension { This extension can register custom global pages (views) to Lens's main window. The global page is a full-screen page that hides all other content from a window. -``` typescript +```typescript import React from "react" import { Component, LensRendererExtension } from "@k8slens/extensions" import { ExamplePage } from "./src/example-page" @@ -123,7 +123,7 @@ export default class ExampleRendererExtension extends LensRendererExtension { This extension can register custom app preferences. It is responsible for storing a state for custom preferences. -``` typescript +```typescript import React from "react" import { LensRendererExtension } from "@k8slens/extensions" import { myCustomPreferencesStore } from "./src/my-custom-preferences-store" @@ -147,7 +147,7 @@ export default class ExampleRendererExtension extends LensRendererExtension { This extension can register custom cluster pages. These pages are visible in a cluster menu when a cluster is opened. -``` typescript +```typescript import React from "react" import { LensRendererExtension } from "@k8slens/extensions"; import { ExampleIcon, ExamplePage } from "./src/page" @@ -180,7 +180,7 @@ export default class ExampleExtension extends LensRendererExtension { This extension can register installable features for a cluster. These features are visible in the "Cluster Settings" page. -``` typescript +```typescript import React from "react" import { LensRendererExtension } from "@k8slens/extensions" import { MyCustomFeature } from "./src/my-custom-feature" @@ -209,18 +209,20 @@ export default class ExampleExtension extends LensRendererExtension { This extension can register custom icons and text to a status bar area. -``` typescript +```typescript import React from "react"; import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions"; export default class ExampleExtension extends LensRendererExtension { statusBarItems = [ { - item: ( -
{ params?: P; query?: Q; + fragment?: string; } export function buildURL
(path: string | any) { const pathBuilder = compile(String(path)); - return function ({ params, query }: IURLParams
= {}) { + return function ({ params, query, fragment }: IURLParams
= {}): string {
const queryParams = query ? new URLSearchParams(Object.entries(query)).toString() : "";
+ const parts = [
+ pathBuilder(params),
+ queryParams && `?${queryParams}`,
+ fragment && `#${fragment}`,
+ ];
- return pathBuilder(params) + (queryParams ? `?${queryParams}` : "");
+ return parts.filter(Boolean).join("");
};
}
diff --git a/src/common/utils/delay.ts b/src/common/utils/delay.ts
new file mode 100644
index 0000000000..f19839538a
--- /dev/null
+++ b/src/common/utils/delay.ts
@@ -0,0 +1,19 @@
+import { AbortController } from "abort-controller";
+
+/**
+ * Return a promise that will be resolved after at least `timeout` ms have
+ * passed. If `failFast` is provided then the promise is also resolved if it has
+ * been aborted.
+ * @param timeout The number of milliseconds before resolving
+ * @param failFast An abort controller instance to cause the delay to short-circuit
+ */
+export function delay(timeout = 1000, failFast?: AbortController): Promise (pageId?: string, params?: P) {
const { navigate } = await import("../renderer/navigation");
@@ -29,8 +30,7 @@ export class LensRendererExtension extends LensExtension {
/**
* Defines if extension is enabled for a given cluster. Defaults to `true`.
*/
- // eslint-disable-next-line unused-imports/no-unused-vars-ts
async isEnabledForCluster(cluster: Cluster): Promise {
export class Router {
protected router: any;
+ protected staticRootPath: string;
public constructor() {
this.router = new Call.Router();
this.addRoutes();
+ this.staticRootPath = this.resolveStaticRootPath();
+ }
+
+ protected resolveStaticRootPath() {
+ return path.resolve(__static);
}
public async route(cluster: Cluster, req: http.IncomingMessage, res: http.ServerResponse): Promise(api: string | KubeApi): S {
- return this.stores.get(this.resolveApi(api)) as S;
+ return this.stores.get(this.resolveApi(api)?.apiBase) as S;
}
}
diff --git a/src/renderer/api/catalog-entity-registry.ts b/src/renderer/api/catalog-entity-registry.ts
new file mode 100644
index 0000000000..afed7a88cf
--- /dev/null
+++ b/src/renderer/api/catalog-entity-registry.ts
@@ -0,0 +1,61 @@
+import { action, observable } from "mobx";
+import { broadcastMessage, subscribeToBroadcast } from "../../common/ipc";
+import { CatalogCategory, CatalogEntity, CatalogEntityData } from "../../common/catalog-entity";
+import { catalogCategoryRegistry, CatalogCategoryRegistry } from "../../common/catalog-category-registry";
+import "../../common/catalog-entities";
+
+export class CatalogEntityRegistry {
+ @observable protected _items: CatalogEntity[] = observable.array([], { deep: true });
+
+ constructor(private categoryRegistry: CatalogCategoryRegistry) {}
+
+ init() {
+ subscribeToBroadcast("catalog:items", (ev, items: CatalogEntityData[]) => {
+ this.updateItems(items);
+ });
+ broadcastMessage("catalog:broadcast");
+ }
+
+ @action updateItems(items: CatalogEntityData[]) {
+ this._items.forEach((item, index) => {
+ const foundIndex = items.findIndex((i) => i.apiVersion === item.apiVersion && i.kind === item.kind && i.metadata.uid === item.metadata.uid);
+
+ if (foundIndex === -1) {
+ this._items.splice(index, 1);
+ }
+ });
+
+ items.forEach((data) => {
+ const item = this.categoryRegistry.getEntityForData(data);
+
+ if (!item) return; // invalid data
+
+ const index = this._items.findIndex((i) => i.apiVersion === item.apiVersion && i.kind === item.kind && i.metadata.uid === item.metadata.uid);
+
+ if (index === -1) {
+ this._items.push(item);
+ } else {
+ this._items.splice(index, 1, item);
+ }
+ });
+ }
+
+ get items() {
+ return this._items;
+ }
+
+ getItemsForApiKindAdd Clusters
>} showOnTop={true}>
Add Clusters from Kubeconfig
{this.renderInfo()}
{this.renderKubeConfigSource()}
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 a33e9d2503..d31efc5438 100644
--- a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx
+++ b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx
@@ -82,9 +82,9 @@ export class HelmChartDetails extends Component