From 1cd9625faad32030884ea3438d91f1b86ca8dd12 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 18 Jul 2022 11:34:40 -0400 Subject: [PATCH] Factor out uses of apiBase that cause test failures Signed-off-by: Sebastian Malton --- src/common/__tests__/hotbar-store.test.ts | 4 +- src/common/helm/chart.ts | 44 ++++ .../k8s-api/__tests__/helm-charts.api.test.ts | 2 +- .../k8s-api/endpoints/helm-releases.api.ts | 227 ------------------ .../utils/environment-variables.injectable.ts | 28 --- src/common/utils/sort-compare.ts | 2 +- src/common/vars/disable-gpu.injectable.ts | 13 + src/common/vars/is-development.injectable.ts | 1 - src/common/vars/is-production.injectable.ts | 9 +- ...tory-for-integration-testing.injectable.ts | 9 +- src/main/getDiForUnitTesting.ts | 12 +- src/main/helm/helm-chart-manager.ts | 2 +- .../setup-hardware-acceleration.injectable.ts | 6 +- .../get-char-details.injectable.ts | 17 -- .../+helm-charts/helm-chart-details.tsx | 2 +- .../helm-chart-store.injectable.ts | 13 - .../components/+helm-charts/helm-charts.tsx | 30 ++- src/renderer/components/+helm-charts/icon.tsx | 2 +- .../+helm-charts/store.injectable.ts | 19 ++ .../{helm-chart.store.ts => store.ts} | 18 +- .../create-release.injectable.ts | 29 --- .../delete-release.injectable.ts | 27 --- .../+helm-releases/dialog/dialog.tsx | 34 +-- .../+helm-releases/dialog/open.injectable.ts | 2 +- .../+helm-releases/dialog/state.injectable.ts | 2 +- .../release-details.injectable.ts | 5 +- .../release-details/release-details.tsx | 14 +- .../release-values.injectable.ts | 21 +- .../release-details/release.injectable.ts | 2 +- .../+helm-releases/release-menu.tsx | 18 +- .../+helm-releases/releases.injectable.ts | 12 +- .../components/+helm-releases/releases.tsx | 4 +- .../removable-releases.injectable.ts | 45 +++- .../+helm-releases/removable-releases.ts | 49 ---- .../rollback-release.injectable.ts | 23 -- .../update-release.injectable.ts | 34 --- .../create-install-chart-tab.injectable.ts | 2 +- .../install-chart-model.injectable.tsx | 4 +- .../dock/install-chart/store.injectable.ts | 6 +- .../components/dock/install-chart/store.ts | 2 +- .../create-upgrade-chart-tab.injectable.ts | 76 +++--- .../dock/upgrade-chart/store.injectable.ts | 2 + .../components/dock/upgrade-chart/store.ts | 5 +- .../components/dock/upgrade-chart/view.tsx | 22 +- src/renderer/getDiForUnitTesting.tsx | 4 + .../k8s/helm-chart.ts} | 104 +------- .../helm-charts.api/get-details.injectable.ts | 50 ++++ .../helm-charts.api/get-values.injectable.ts | 26 ++ .../k8s/helm-charts.api/list.injectable.ts | 33 +++ src/renderer/k8s/helm-release.ts | 26 ++ src/renderer/k8s/helm-releases.api.ts | 31 +++ .../helm-releases.api/create.injectable.ts | 49 ++++ .../helm-releases.api/delete.injectable.ts | 29 +++ .../get-details.injectable.ts | 21 ++ .../get-history.injectable.ts | 31 +++ .../get-values.injectable.ts | 28 +++ .../k8s/helm-releases.api/list.injectable.ts | 27 +++ .../helm-releases.api/rollback.injectable.ts | 34 +++ .../to-instance.injectable.ts | 87 +++++++ .../helm-releases.api/update.injectable.ts | 48 ++++ 60 files changed, 811 insertions(+), 717 deletions(-) create mode 100644 src/common/helm/chart.ts delete mode 100644 src/common/k8s-api/endpoints/helm-releases.api.ts delete mode 100644 src/common/utils/environment-variables.injectable.ts create mode 100644 src/common/vars/disable-gpu.injectable.ts delete mode 100644 src/renderer/components/+helm-charts/get-char-details.injectable.ts delete mode 100644 src/renderer/components/+helm-charts/helm-chart-store.injectable.ts create mode 100644 src/renderer/components/+helm-charts/store.injectable.ts rename src/renderer/components/+helm-charts/{helm-chart.store.ts => store.ts} (80%) delete mode 100644 src/renderer/components/+helm-releases/create-release/create-release.injectable.ts delete mode 100644 src/renderer/components/+helm-releases/delete-release/delete-release.injectable.ts delete mode 100644 src/renderer/components/+helm-releases/removable-releases.ts delete mode 100644 src/renderer/components/+helm-releases/rollback-release/rollback-release.injectable.ts delete mode 100644 src/renderer/components/+helm-releases/update-release/update-release.injectable.ts rename src/{common/k8s-api/endpoints/helm-charts.api.ts => renderer/k8s/helm-chart.ts} (68%) create mode 100644 src/renderer/k8s/helm-charts.api/get-details.injectable.ts create mode 100644 src/renderer/k8s/helm-charts.api/get-values.injectable.ts create mode 100644 src/renderer/k8s/helm-charts.api/list.injectable.ts create mode 100644 src/renderer/k8s/helm-release.ts create mode 100644 src/renderer/k8s/helm-releases.api.ts create mode 100644 src/renderer/k8s/helm-releases.api/create.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/delete.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/get-details.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/get-history.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/get-values.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/list.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/rollback.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/to-instance.injectable.ts create mode 100644 src/renderer/k8s/helm-releases.api/update.injectable.ts diff --git a/src/common/__tests__/hotbar-store.test.ts b/src/common/__tests__/hotbar-store.test.ts index 1761b4e983..7973e4672e 100644 --- a/src/common/__tests__/hotbar-store.test.ts +++ b/src/common/__tests__/hotbar-store.test.ts @@ -19,6 +19,7 @@ import catalogGeneralEntityInjectable from "../catalog-entities/general-catalog- import loggerInjectable from "../logger.injectable"; import type { Logger } from "../logger"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import fsInjectable from "../fs/fs.injectable"; function getMockCatalogEntity(data: Partial & CatalogEntityKindData): CatalogEntity { return { @@ -46,7 +47,7 @@ describe("HotbarStore", () => { beforeEach(async () => { di = getDiForUnitTesting({ doGeneralOverrides: true }); - (di as any).unoverride(hotbarStoreInjectable); + di.unoverride(hotbarStoreInjectable); testCluster = getMockCatalogEntity({ apiVersion: "v1", @@ -115,6 +116,7 @@ describe("HotbarStore", () => { di.permitSideEffects(getConfigurationFileModelInjectable); di.permitSideEffects(appVersionInjectable); di.permitSideEffects(hotbarStoreInjectable); + di.permitSideEffects(fsInjectable); }); afterEach(() => { diff --git a/src/common/helm/chart.ts b/src/common/helm/chart.ts new file mode 100644 index 0000000000..38a3657e2e --- /dev/null +++ b/src/common/helm/chart.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +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; +} + +export interface HelmChartMaintainer { + name: string; + email: string; + url?: string; +} + +export interface RawHelmChartDependency { + name: string; + repository: string; + condition?: string; + version: string; + tags?: string[]; +} + +export type RepoHelmChartList = Record; diff --git a/src/common/k8s-api/__tests__/helm-charts.api.test.ts b/src/common/k8s-api/__tests__/helm-charts.api.test.ts index e7a4cb9439..9312b154b7 100644 --- a/src/common/k8s-api/__tests__/helm-charts.api.test.ts +++ b/src/common/k8s-api/__tests__/helm-charts.api.test.ts @@ -4,7 +4,7 @@ */ import { anyObject } from "jest-mock-extended"; -import { HelmChart } from "../endpoints/helm-charts.api"; +import { HelmChart } from "../../../renderer/k8s/helm-chart"; describe("HelmChart tests", () => { describe("HelmChart.create() tests", () => { diff --git a/src/common/k8s-api/endpoints/helm-releases.api.ts b/src/common/k8s-api/endpoints/helm-releases.api.ts deleted file mode 100644 index b3922276bd..0000000000 --- a/src/common/k8s-api/endpoints/helm-releases.api.ts +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import yaml from "js-yaml"; -import { formatDuration } from "../../utils"; -import capitalize from "lodash/capitalize"; -import { apiBase } from "../index"; -import { helmChartStore } from "../../../renderer/components/+helm-charts/helm-chart.store"; -import type { ItemObject } from "../../item.store"; -import type { JsonApiData } from "../json-api"; -import { buildURLPositional } from "../../utils/buildUrl"; -import type { KubeJsonApiData } from "../kube-json-api"; - -export interface HelmReleaseDetails { - resources: KubeJsonApiData[]; - name: string; - namespace: string; - version: string; - config: string; // release values - manifest: string; - info: { - deleted: string; - description: string; - first_deployed: string; - last_deployed: string; - notes: string; - status: string; - }; -} - -export interface HelmReleaseCreatePayload { - name?: string; - repo: string; - chart: string; - namespace: string; - version: string; - values: string; -} - -export interface HelmReleaseUpdatePayload { - repo: string; - chart: string; - version: string; - values: string; -} - -export interface HelmReleaseUpdateDetails { - log: string; - release: HelmReleaseDetails; -} - -export interface HelmReleaseRevision { - revision: number; - updated: string; - status: string; - chart: string; - app_version: string; - description: string; -} - -type EndpointParams = {} - | { namespace: string } - | { namespace: string; name: string } - | { namespace: string; name: string; route: string }; - -interface EndpointQuery { - all?: boolean; -} - -const endpoint = buildURLPositional("/v2/releases/:namespace?/:name?/:route?"); - -export async function listReleases(namespace?: string): Promise { - const releases = await apiBase.get(endpoint({ namespace })); - - return releases.map(toHelmRelease); -} - -export async function getRelease(name: string, namespace: string): Promise { - const path = endpoint({ name, namespace }); - - return apiBase.get(path); -} - -export async function createRelease(payload: HelmReleaseCreatePayload): Promise { - const { repo, chart: rawChart, values: rawValues, ...data } = payload; - const chart = `${repo}/${rawChart}`; - const values = yaml.load(rawValues); - - return apiBase.post(endpoint(), { - data: { - chart, - values, - ...data, - }, - }); -} - -export async function updateRelease(name: string, namespace: string, payload: HelmReleaseUpdatePayload): Promise { - const { repo, chart: rawChart, values: rawValues, ...data } = payload; - const chart = `${repo}/${rawChart}`; - const values = yaml.load(rawValues); - - return apiBase.put(endpoint({ name, namespace }), { - data: { - chart, - values, - ...data, - }, - }); -} - -export async function deleteRelease(name: string, namespace: string): Promise { - const path = endpoint({ name, namespace }); - - return apiBase.del(path); -} - -export async function getReleaseValues(name: string, namespace: string, all?: boolean): Promise { - const route = "values"; - const path = endpoint({ name, namespace, route }, { all }); - - return apiBase.get(path); -} - -export async function getReleaseHistory(name: string, namespace: string): Promise { - const route = "history"; - const path = endpoint({ name, namespace, route }); - - return apiBase.get(path); -} - -export async function rollbackRelease(name: string, namespace: string, revision: number): Promise { - const route = "rollback"; - const path = endpoint({ name, namespace, route }); - const data = { revision }; - - return apiBase.put(path, { data }); -} - -interface HelmReleaseDto { - appVersion: string; - name: string; - namespace: string; - chart: string; - status: string; - updated: string; - revision: string; -} - -export interface HelmRelease extends HelmReleaseDto, ItemObject { - getNs: () => string; - getChart: (withVersion?: boolean) => string; - getRevision: () => number; - getStatus: () => string; - getVersion: () => string; - getUpdated: (humanize?: boolean, compact?: boolean) => string | number; - getRepo: () => Promise; -} - -const toHelmRelease = (release: HelmReleaseDto) : HelmRelease => ({ - ...release, - - getId() { - return this.namespace + this.name; - }, - - getName() { - return this.name; - }, - - getNs() { - return this.namespace; - }, - - getChart(withVersion = false) { - let chart = this.chart; - - if (!withVersion && this.getVersion() != "") { - const search = new RegExp(`-${this.getVersion()}`); - - chart = chart.replace(search, ""); - } - - return chart; - }, - - getRevision() { - return parseInt(this.revision, 10); - }, - - getStatus() { - return capitalize(this.status); - }, - - getVersion() { - const versions = this.chart.match(/(?<=-)(v?\d+)[^-].*$/); - - return versions?.[0] ?? ""; - }, - - getUpdated(humanize = true, compact = true) { - const updated = this.updated.replace(/\s\w*$/, ""); // 2019-11-26 10:58:09 +0300 MSK -> 2019-11-26 10:58:09 +0300 to pass into Date() - const updatedDate = new Date(updated).getTime(); - const diff = Date.now() - updatedDate; - - if (humanize) { - return formatDuration(diff, compact); - } - - return diff; - }, - - // Helm does not store from what repository the release is installed, - // so we have to try to guess it by searching charts - async getRepo() { - const chartName = this.getChart(); - const version = this.getVersion(); - const versions = await helmChartStore.getVersions(chartName); - const chartVersion = versions.find( - (chartVersion) => chartVersion.version === version, - ); - - return chartVersion ? chartVersion.repo : ""; - }, -}); diff --git a/src/common/utils/environment-variables.injectable.ts b/src/common/utils/environment-variables.injectable.ts deleted file mode 100644 index 8df689cc3f..0000000000 --- a/src/common/utils/environment-variables.injectable.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; - -const environmentVariablesInjectable = getInjectable({ - id: "environment-variables", - - instantiate: () => { - // IMPORTANT: The syntax needs to be exactly this in order to make environment variable values - // hard-coded at compile-time by Webpack. - const NODE_ENV = process.env.NODE_ENV; - - return { - // Compile-time environment variables - NODE_ENV, - - // Runtime environment variables - CICD: process.env.CICD, - LENS_DISABLE_GPU: process.env.LENS_DISABLE_GPU, - }; - }, - - causesSideEffects: true, -}); - -export default environmentVariablesInjectable; diff --git a/src/common/utils/sort-compare.ts b/src/common/utils/sort-compare.ts index df4c59b961..01af6f5fc3 100644 --- a/src/common/utils/sort-compare.ts +++ b/src/common/utils/sort-compare.ts @@ -6,8 +6,8 @@ import type { SemVer } from "semver"; import semver, { coerce } from "semver"; import * as iter from "./iter"; -import type { RawHelmChart } from "../k8s-api/endpoints/helm-charts.api"; import logger from "../logger"; +import type { RawHelmChart } from "../helm/chart"; export enum Ordering { LESS = -1, diff --git a/src/common/vars/disable-gpu.injectable.ts b/src/common/vars/disable-gpu.injectable.ts new file mode 100644 index 0000000000..2801b1051d --- /dev/null +++ b/src/common/vars/disable-gpu.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; + +const hardwareAccelerationShouldBeDisabledInjectable = getInjectable({ + id: "hardware-acceleration-should-be-disabled", + instantiate: () => Boolean(process.env.LENS_DISABLE_GPU), + causesSideEffects: true, +}); + +export default hardwareAccelerationShouldBeDisabledInjectable; diff --git a/src/common/vars/is-development.injectable.ts b/src/common/vars/is-development.injectable.ts index 697d7b5ce6..af7aeb3b91 100644 --- a/src/common/vars/is-development.injectable.ts +++ b/src/common/vars/is-development.injectable.ts @@ -7,7 +7,6 @@ import isProductionInjectable from "./is-production.injectable"; const isDevelopmentInjectable = getInjectable({ id: "is-development", - instantiate: (di) => !di.inject(isProductionInjectable), }); diff --git a/src/common/vars/is-production.injectable.ts b/src/common/vars/is-production.injectable.ts index 085b091dfa..68fcfb3d49 100644 --- a/src/common/vars/is-production.injectable.ts +++ b/src/common/vars/is-production.injectable.ts @@ -3,16 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import environmentVariablesInjectable from "../utils/environment-variables.injectable"; const isProductionInjectable = getInjectable({ id: "is-production", - - instantiate: (di) => { - const { NODE_ENV: nodeEnv } = di.inject(environmentVariablesInjectable); - - return nodeEnv === "production"; - }, + instantiate: () => process.env.NODE_ENV === "production", + causesSideEffects: true, }); export default isProductionInjectable; diff --git a/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.injectable.ts b/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.injectable.ts index 73647a3270..7a98699fee 100644 --- a/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.injectable.ts +++ b/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.injectable.ts @@ -3,16 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import environmentVariablesInjectable from "../../../common/utils/environment-variables.injectable"; const directoryForIntegrationTestingInjectable = getInjectable({ id: "directory-for-integration-testing", - - instantiate: (di) => { - const environmentVariables = di.inject(environmentVariablesInjectable); - - return environmentVariables.CICD; - }, + instantiate: () => process.env.CICD, + causesSideEffects: true, }); export default directoryForIntegrationTestingInjectable; diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index 8a09dbeab5..b9b59e67e7 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -31,7 +31,6 @@ import hotbarStoreInjectable from "../common/hotbars/store.injectable"; import commandLineArgumentsInjectable from "./utils/command-line-arguments.injectable"; import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable"; import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.injectable"; -import environmentVariablesInjectable from "../common/utils/environment-variables.injectable"; import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable"; import setupLensProxyInjectable from "./start-main-application/runnables/setup-lens-proxy.injectable"; import setupSentryInjectable from "./start-main-application/runnables/setup-sentry.injectable"; @@ -39,7 +38,6 @@ import setupShellInjectable from "./start-main-application/runnables/setup-shell import setupSyncingOfWeblinksInjectable from "./start-main-application/runnables/setup-syncing-of-weblinks.injectable"; import stopServicesAndExitAppInjectable from "./stop-services-and-exit-app.injectable"; import applicationMenuInjectable from "./menu/application-menu.injectable"; -import isDevelopmentInjectable from "../common/vars/is-development.injectable"; import setupSystemCaInjectable from "./start-main-application/runnables/setup-system-ca.injectable"; import setupDeepLinkingInjectable from "./electron-app/runnables/setup-deep-linking.injectable"; import exitAppInjectable from "./electron-app/features/exit-app.injectable"; @@ -99,6 +97,10 @@ import electronInjectable from "./utils/resolve-system-proxy/electron.injectable import type { HotbarStore } from "../common/hotbars/store"; import focusApplicationInjectable from "./electron-app/features/focus-application.injectable"; import migrationLogInjectable from "./migrations/log.injectable"; +import hardwareAccelerationShouldBeDisabledInjectable from "../common/vars/disable-gpu.injectable"; +import directoryForIntegrationTestingInjectable from "./app-paths/directory-for-integration-testing/directory-for-integration-testing.injectable"; +import isProductionInjectable from "../common/vars/is-production.injectable"; +import isDebuggingInjectable from "../common/vars/is-debugging.injectable"; export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) { const { @@ -141,8 +143,10 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) overrideRunnablesHavingSideEffects(di); overrideElectronFeatures(di); - di.override(isDevelopmentInjectable, () => false); - di.override(environmentVariablesInjectable, () => ({})); + di.override(isProductionInjectable, () => true); + di.override(isDebuggingInjectable, () => false); + di.override(hardwareAccelerationShouldBeDisabledInjectable, () => false); + di.override(directoryForIntegrationTestingInjectable, () => undefined); di.override(commandLineArgumentsInjectable, () => []); di.override(productNameInjectable, () => "some-product-name"); diff --git a/src/main/helm/helm-chart-manager.ts b/src/main/helm/helm-chart-manager.ts index 8ba7a83101..85ac56b1d8 100644 --- a/src/main/helm/helm-chart-manager.ts +++ b/src/main/helm/helm-chart-manager.ts @@ -6,12 +6,12 @@ import fs from "fs"; import * as yaml from "js-yaml"; import logger from "../logger"; -import type { RepoHelmChartList } from "../../common/k8s-api/endpoints/helm-charts.api"; import { iter, put, sortCharts } from "../../common/utils"; import { execHelm } from "./exec"; import type { SetRequired } from "type-fest"; import { assert } from "console"; import type { HelmRepo } from "../../common/helm/helm-repo"; +import type { RepoHelmChartList } from "../../common/helm/chart"; interface ChartCacheEntry { data: string; // serialized JSON diff --git a/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts b/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts index ba1b5f2bb8..643b90727a 100644 --- a/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts +++ b/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import environmentVariablesInjectable from "../../../common/utils/environment-variables.injectable"; +import hardwareAccelerationShouldBeDisabledInjectable from "../../../common/vars/disable-gpu.injectable"; import disableHardwareAccelerationInjectable from "../../electron-app/features/disable-hardware-acceleration.injectable"; import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/before-electron-is-ready-injection-token"; @@ -11,12 +11,12 @@ const setupHardwareAccelerationInjectable = getInjectable({ id: "setup-hardware-acceleration", instantiate: (di) => { - const { LENS_DISABLE_GPU: hardwareAccelerationShouldBeDisabled } = di.inject(environmentVariablesInjectable); + const disableGpuAcceleration = di.inject(hardwareAccelerationShouldBeDisabledInjectable); const disableHardwareAcceleration = di.inject(disableHardwareAccelerationInjectable); return { run: () => { - if (hardwareAccelerationShouldBeDisabled) { + if (disableGpuAcceleration) { disableHardwareAcceleration(); } }, diff --git a/src/renderer/components/+helm-charts/get-char-details.injectable.ts b/src/renderer/components/+helm-charts/get-char-details.injectable.ts deleted file mode 100644 index e2c5ccca62..0000000000 --- a/src/renderer/components/+helm-charts/get-char-details.injectable.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { GetChartDetailsOptions, IHelmChartDetails } from "../../../common/k8s-api/endpoints/helm-charts.api"; -import { getChartDetails } from "../../../common/k8s-api/endpoints/helm-charts.api"; - -export type GetChartDetails = (repo: string, name: string, opts?: GetChartDetailsOptions) => Promise; - -const getChartDetailsInjectable = getInjectable({ - id: "get-chart-details", - instantiate: (): GetChartDetails => getChartDetails, - causesSideEffects: true, -}); - -export default getChartDetailsInjectable; diff --git a/src/renderer/components/+helm-charts/helm-chart-details.tsx b/src/renderer/components/+helm-charts/helm-chart-details.tsx index d15552dedb..c8f58a43c8 100644 --- a/src/renderer/components/+helm-charts/helm-chart-details.tsx +++ b/src/renderer/components/+helm-charts/helm-chart-details.tsx @@ -6,7 +6,7 @@ import "./helm-chart-details.scss"; import React, { Component } from "react"; -import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; +import type { HelmChart } from "../../k8s/helm-chart"; import { observer } from "mobx-react"; import { Drawer, DrawerItem } from "../drawer"; import { autoBind, stopPropagation } from "../../utils"; diff --git a/src/renderer/components/+helm-charts/helm-chart-store.injectable.ts b/src/renderer/components/+helm-charts/helm-chart-store.injectable.ts deleted file mode 100644 index ac05d23368..0000000000 --- a/src/renderer/components/+helm-charts/helm-chart-store.injectable.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { HelmChartStore } from "./helm-chart.store"; - -const helmChartStoreInjectable = getInjectable({ - id: "helm-chart-store", - instantiate: () => new HelmChartStore(), -}); - -export default helmChartStoreInjectable; diff --git a/src/renderer/components/+helm-charts/helm-charts.tsx b/src/renderer/components/+helm-charts/helm-charts.tsx index 5a603cf7aa..1b91cdcf81 100644 --- a/src/renderer/components/+helm-charts/helm-charts.tsx +++ b/src/renderer/components/+helm-charts/helm-charts.tsx @@ -7,8 +7,7 @@ import "./helm-charts.scss"; import React, { Component } from "react"; import { observer } from "mobx-react"; -import { helmChartStore } from "./helm-chart.store"; -import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; +import type { HelmChart } from "../../k8s/helm-chart"; import { HelmChartDetails } from "./helm-chart-details"; import { ItemListLayout } from "../item-object-list/list-layout"; import type { IComputedValue } from "mobx"; @@ -21,6 +20,8 @@ import navigateToHelmChartsInjectable from "../../../common/front-end-routing/ro import { HelmChartIcon } from "./icon"; import helmChartsInjectable from "./helm-charts/helm-charts.injectable"; import selectedHelmChartInjectable from "./helm-charts/selected-helm-chart.injectable"; +import type { HelmChartStore } from "./store"; +import helmChartStoreInjectable from "./store.injectable"; enum columnId { name = "name", @@ -35,7 +36,7 @@ interface Dependencies { chartName: IComputedValue; repo: IComputedValue; }; - + helmChartStore: HelmChartStore; navigateToHelmCharts: NavigateToHelmCharts; charts: IAsyncComputed; @@ -79,7 +80,7 @@ class NonInjectedHelmCharts extends Component { isConfigurable tableId="helm_charts" className="HelmCharts" - store={helmChartStore} + store={this.props.helmChartStore} getItems={() => this.props.charts.value.get()} isSelectable={false} sortingCallbacks={{ @@ -132,16 +133,13 @@ class NonInjectedHelmCharts extends Component { } } -export const HelmCharts = withInjectables( - NonInjectedHelmCharts, - - { - getProps: (di) => ({ - routeParameters: di.inject(helmChartsRouteParametersInjectable), - navigateToHelmCharts: di.inject(navigateToHelmChartsInjectable), - charts: di.inject(helmChartsInjectable), - selectedChart: di.inject(selectedHelmChartInjectable), - }), - }, -); +export const HelmCharts = withInjectables(NonInjectedHelmCharts, { + getProps: (di) => ({ + routeParameters: di.inject(helmChartsRouteParametersInjectable), + navigateToHelmCharts: di.inject(navigateToHelmChartsInjectable), + helmChartStore: di.inject(helmChartStoreInjectable), + charts: di.inject(helmChartsInjectable), + selectedChart: di.inject(selectedHelmChartInjectable), + }), +}); diff --git a/src/renderer/components/+helm-charts/icon.tsx b/src/renderer/components/+helm-charts/icon.tsx index 78d5be7ed3..272328a1d3 100644 --- a/src/renderer/components/+helm-charts/icon.tsx +++ b/src/renderer/components/+helm-charts/icon.tsx @@ -4,7 +4,7 @@ */ import React, { useState } from "react"; -import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; +import type { HelmChart } from "../../k8s/helm-chart"; export interface HelmChartIconProps { className?: string; diff --git a/src/renderer/components/+helm-charts/store.injectable.ts b/src/renderer/components/+helm-charts/store.injectable.ts new file mode 100644 index 0000000000..d35c5e4071 --- /dev/null +++ b/src/renderer/components/+helm-charts/store.injectable.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectable } from "@ogre-tools/injectable"; +import getHelmChartDetailsInjectable from "../../k8s/helm-charts.api/get-details.injectable"; +import listHelmChartsInjectable from "../../k8s/helm-charts.api/list.injectable"; +import { HelmChartStore } from "./store"; + +const helmChartStoreInjectable = getInjectable({ + id: "helm-chart-store", + instantiate: (di) => new HelmChartStore({ + listHelmCharts: di.inject(listHelmChartsInjectable), + getHelmChartDetails: di.inject(getHelmChartDetailsInjectable), + }), +}); + +export default helmChartStoreInjectable; diff --git a/src/renderer/components/+helm-charts/helm-chart.store.ts b/src/renderer/components/+helm-charts/store.ts similarity index 80% rename from src/renderer/components/+helm-charts/helm-chart.store.ts rename to src/renderer/components/+helm-charts/store.ts index 1a3c4d7d7f..d379f4b7b4 100644 --- a/src/renderer/components/+helm-charts/helm-chart.store.ts +++ b/src/renderer/components/+helm-charts/store.ts @@ -6,20 +6,26 @@ import semver from "semver"; import { observable, makeObservable } from "mobx"; import { autoBind, sortCompareChartVersions } from "../../utils"; -import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; -import { getChartDetails, listCharts } from "../../../common/k8s-api/endpoints/helm-charts.api"; +import type { HelmChart } from "../../k8s/helm-chart"; import { ItemStore } from "../../../common/item.store"; import flatten from "lodash/flatten"; +import type { ListHelmCharts } from "../../k8s/helm-charts.api/list.injectable"; +import type { GetHelmChartDetails } from "../../k8s/helm-charts.api/get-details.injectable"; export interface ChartVersion { repo: string; version: string; } +export interface HelmChartStoreDependencies { + listHelmCharts: ListHelmCharts; + getHelmChartDetails: GetHelmChartDetails; +} + export class HelmChartStore extends ItemStore { @observable versions = observable.map(); - constructor() { + constructor(protected readonly dependencies: HelmChartStoreDependencies) { super(); makeObservable(this); @@ -28,7 +34,7 @@ export class HelmChartStore extends ItemStore { async loadAll() { try { - const res = await this.loadItems(() => listCharts()); + const res = await this.loadItems(() => this.dependencies.listHelmCharts()); this.failedLoading = false; @@ -68,7 +74,7 @@ export class HelmChartStore extends ItemStore { } const loadVersions = async (repo: string) => { - const { versions } = await getChartDetails(repo, chartName); + const { versions } = await this.dependencies.getHelmChartDetails(repo, chartName); return versions.map(chart => ({ repo, @@ -104,5 +110,3 @@ export class HelmChartStore extends ItemStore { throw new Error("removeItems is not supported"); } } - -export const helmChartStore = new HelmChartStore(); diff --git a/src/renderer/components/+helm-releases/create-release/create-release.injectable.ts b/src/renderer/components/+helm-releases/create-release/create-release.injectable.ts deleted file mode 100644 index b2e292b034..0000000000 --- a/src/renderer/components/+helm-releases/create-release/create-release.injectable.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; - -import type { - HelmReleaseCreatePayload } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import releasesInjectable from "../releases.injectable"; -import callForCreateHelmReleaseInjectable from "./call-for-create-helm-release.injectable"; - -const createReleaseInjectable = getInjectable({ - id: "create-release", - - instantiate: (di) => { - const releases = di.inject(releasesInjectable); - const callForCreateRelease = di.inject(callForCreateHelmReleaseInjectable); - - return async (payload: HelmReleaseCreatePayload) => { - const release = await callForCreateRelease(payload); - - releases.invalidate(); - - return release; - }; - }, -}); - -export default createReleaseInjectable; diff --git a/src/renderer/components/+helm-releases/delete-release/delete-release.injectable.ts b/src/renderer/components/+helm-releases/delete-release/delete-release.injectable.ts deleted file mode 100644 index 4619ddaf1f..0000000000 --- a/src/renderer/components/+helm-releases/delete-release/delete-release.injectable.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { - HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { - deleteRelease, -} from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import releasesInjectable from "../releases.injectable"; - -const deleteReleaseInjectable = getInjectable({ - id: "delete-release", - - instantiate: (di) => { - const releases = di.inject(releasesInjectable); - - return async (release: HelmRelease) => { - await deleteRelease(release.getName(), release.getNs()); - - releases.invalidate(); - }; - }, -}); - -export default deleteReleaseInjectable; diff --git a/src/renderer/components/+helm-releases/dialog/dialog.tsx b/src/renderer/components/+helm-releases/dialog/dialog.tsx index 5655720e10..d8aaf64632 100644 --- a/src/renderer/components/+helm-releases/dialog/dialog.tsx +++ b/src/renderer/components/+helm-releases/dialog/dialog.tsx @@ -12,21 +12,24 @@ import { observer } from "mobx-react"; import type { DialogProps } from "../../dialog"; import { Dialog } from "../../dialog"; import { Wizard, WizardStep } from "../../wizard"; -import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { getReleaseHistory, type HelmReleaseRevision } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import { Select } from "../../select"; import { Notifications } from "../../notifications"; import orderBy from "lodash/orderBy"; import { withInjectables } from "@ogre-tools/injectable-react"; import releaseRollbackDialogStateInjectable from "./state.injectable"; -import rollbackReleaseInjectable from "../rollback-release/rollback-release.injectable"; +import type { HelmRelease } from "../../../k8s/helm-release"; +import type { GetHelmReleaseHistory, HelmReleaseRevision } from "../../../k8s/helm-releases.api/get-history.injectable"; +import type { RollbackHelmRelease } from "../../../k8s/helm-releases.api/rollback.injectable"; +import rollbackHelmReleaseInjectable from "../../../k8s/helm-releases.api/rollback.injectable"; +import getHelmReleaseHistoryInjectable from "../../../k8s/helm-releases.api/get-history.injectable"; export interface ReleaseRollbackDialogProps extends DialogProps { } interface Dependencies { - rollbackRelease: (releaseName: string, namespace: string, revisionNumber: number) => Promise; + rollbackHelmRelease: RollbackHelmRelease; state: IObservableValue; + getHelmReleaseHistory: GetHelmReleaseHistory; } @observer @@ -48,7 +51,7 @@ class NonInjectedReleaseRollbackDialog extends React.Component { this.isLoading.set(true); - const releases = await getReleaseHistory(release.getName(), release.getNs()); + const releases = await this.props.getHelmReleaseHistory(release.getName(), release.getNs()); runInAction(() => { this.revisions.replace(orderBy(releases, "revision", "desc")); @@ -65,7 +68,7 @@ class NonInjectedReleaseRollbackDialog extends React.Component( - NonInjectedReleaseRollbackDialog, - - { - getProps: (di, props) => ({ - rollbackRelease: di.inject(rollbackReleaseInjectable), - state: di.inject(releaseRollbackDialogStateInjectable), - ...props, - }), - }, -); +export const ReleaseRollbackDialog = withInjectables(NonInjectedReleaseRollbackDialog, { + getProps: (di, props) => ({ + ...props, + rollbackHelmRelease: di.inject(rollbackHelmReleaseInjectable), + state: di.inject(releaseRollbackDialogStateInjectable), + getHelmReleaseHistory: di.inject(getHelmReleaseHistoryInjectable), + }), +}); diff --git a/src/renderer/components/+helm-releases/dialog/open.injectable.ts b/src/renderer/components/+helm-releases/dialog/open.injectable.ts index da1ec2106d..7c685508d7 100644 --- a/src/renderer/components/+helm-releases/dialog/open.injectable.ts +++ b/src/renderer/components/+helm-releases/dialog/open.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; -import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; +import type { HelmRelease } from "../../../k8s/helm-release"; import releaseRollbackDialogStateInjectable from "./state.injectable"; export type OpenHelmReleaseRollbackDialog = (release: HelmRelease) => void; diff --git a/src/renderer/components/+helm-releases/dialog/state.injectable.ts b/src/renderer/components/+helm-releases/dialog/state.injectable.ts index 4551eab915..9d33ed1bb0 100644 --- a/src/renderer/components/+helm-releases/dialog/state.injectable.ts +++ b/src/renderer/components/+helm-releases/dialog/state.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { observable } from "mobx"; -import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; +import type { HelmRelease } from "../../../k8s/helm-release"; const releaseRollbackDialogStateInjectable = getInjectable({ id: "release-rollback-dialog-state", diff --git a/src/renderer/components/+helm-releases/release-details/release-details.injectable.ts b/src/renderer/components/+helm-releases/release-details/release-details.injectable.ts index f788d5ac57..729a5e99a6 100644 --- a/src/renderer/components/+helm-releases/release-details/release-details.injectable.ts +++ b/src/renderer/components/+helm-releases/release-details/release-details.injectable.ts @@ -3,21 +3,22 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { getRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import { asyncComputed } from "@ogre-tools/injectable-react"; import releaseInjectable from "./release.injectable"; import { waitUntilDefined } from "../../../utils"; +import getHelmReleaseDetailsInjectable from "../../../k8s/helm-releases.api/get-details.injectable"; const releaseDetailsInjectable = getInjectable({ id: "release-details", instantiate: (di) => { const releaseComputed = di.inject(releaseInjectable); + const getHelmReleaseDetails = di.inject(getHelmReleaseDetailsInjectable); return asyncComputed(async () => { const release = await waitUntilDefined(releaseComputed); - return getRelease(release.name, release.namespace); + return getHelmReleaseDetails(release.name, release.namespace); });}, }); diff --git a/src/renderer/components/+helm-releases/release-details/release-details.tsx b/src/renderer/components/+helm-releases/release-details/release-details.tsx index ee01070fbf..e830ccc680 100644 --- a/src/renderer/components/+helm-releases/release-details/release-details.tsx +++ b/src/renderer/components/+helm-releases/release-details/release-details.tsx @@ -11,7 +11,6 @@ import type { IComputedValue } from "mobx"; import { computed, makeObservable, observable } from "mobx"; import { Link } from "react-router-dom"; import kebabCase from "lodash/kebabCase"; -import type { HelmRelease, HelmReleaseDetails, HelmReleaseUpdateDetails, HelmReleaseUpdatePayload } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import { HelmReleaseMenu } from "../release-menu"; import { Drawer, DrawerItem, DrawerTitle } from "../../drawer"; import { Badge } from "../../badge"; @@ -29,7 +28,6 @@ import { MonacoEditor } from "../../monaco-editor"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import createUpgradeChartTabInjectable from "../../dock/upgrade-chart/create-upgrade-chart-tab.injectable"; -import updateReleaseInjectable from "../update-release/update-release.injectable"; import releaseInjectable from "./release.injectable"; import releaseDetailsInjectable from "./release-details.injectable"; import releaseValuesInjectable from "./release-values.injectable"; @@ -41,16 +39,20 @@ import themeStoreInjectable from "../../../themes/store.injectable"; import type { GetDetailsUrl } from "../../kube-detail-params/get-details-url.injectable"; import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; import getDetailsUrlInjectable from "../../kube-detail-params/get-details-url.injectable"; +import type { HelmRelease } from "../../../k8s/helm-release"; +import type { HelmReleaseDetails } from "../../../k8s/helm-releases.api"; +import type { UpdateHelmRelease } from "../../../k8s/helm-releases.api/update.injectable"; +import updateHelmReleaseInjectable from "../../../k8s/helm-releases.api/update.injectable"; export interface ReleaseDetailsProps { hideDetails(): void; } interface Dependencies { - release: IComputedValue; + release: IComputedValue; releaseDetails: IAsyncComputed; releaseValues: IAsyncComputed; - updateRelease: (name: string, namespace: string, payload: HelmReleaseUpdatePayload) => Promise; + updateHelmRelease: UpdateHelmRelease; createUpgradeChartTab: (release: HelmRelease) => void; userSuppliedValuesAreShown: { toggle: () => void; value: boolean }; themeStore: ThemeStore; @@ -86,7 +88,7 @@ class NonInjectedReleaseDetails extends Component Release @@ -291,7 +293,7 @@ export const ReleaseDetails = withInjectables releaseDetails: di.inject(releaseDetailsInjectable), releaseValues: di.inject(releaseValuesInjectable), userSuppliedValuesAreShown: di.inject(userSuppliedValuesAreShownInjectable), - updateRelease: di.inject(updateReleaseInjectable), + updateHelmRelease: di.inject(updateHelmReleaseInjectable), createUpgradeChartTab: di.inject(createUpgradeChartTabInjectable), themeStore: di.inject(themeStoreInjectable), apiManager: di.inject(apiManagerInjectable), diff --git a/src/renderer/components/+helm-releases/release-details/release-values.injectable.ts b/src/renderer/components/+helm-releases/release-details/release-values.injectable.ts index 96cfd6c2dd..f35c31c79f 100644 --- a/src/renderer/components/+helm-releases/release-details/release-values.injectable.ts +++ b/src/renderer/components/+helm-releases/release-details/release-values.injectable.ts @@ -3,17 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { getReleaseValues } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import { asyncComputed } from "@ogre-tools/injectable-react"; import releaseInjectable from "./release.injectable"; -import { Notifications } from "../../notifications"; import userSuppliedValuesAreShownInjectable from "./user-supplied-values-are-shown.injectable"; +import getHelmReleaseValuesInjectable from "../../../k8s/helm-releases.api/get-values.injectable"; +import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable"; const releaseValuesInjectable = getInjectable({ id: "release-values", - instantiate: (di) => - asyncComputed(async () => { + instantiate: (di) => { + const getHelmReleaseValues = di.inject(getHelmReleaseValuesInjectable); + const showErrorNotification = di.inject(showErrorNotificationInjectable); + const userSuppliedValuesAreShown = di.inject(userSuppliedValuesAreShownInjectable); + + return asyncComputed(async () => { const release = di.inject(releaseInjectable).get(); // TODO: Figure out way to get rid of defensive code @@ -21,16 +25,15 @@ const releaseValuesInjectable = getInjectable({ return ""; } - const userSuppliedValuesAreShown = di.inject(userSuppliedValuesAreShownInjectable).value; - try { - return await getReleaseValues(release.getName(), release.getNs(), !userSuppliedValuesAreShown) ?? ""; + return await getHelmReleaseValues(release.getName(), release.getNs(), !userSuppliedValuesAreShown.value) ?? ""; } catch (error) { - Notifications.error(`Failed to load values for ${release.getName()}: ${error}`); + showErrorNotification(`Failed to load values for ${release.getName()}: ${error}`); return ""; } - }), + }); + }, }); export default releaseValuesInjectable; diff --git a/src/renderer/components/+helm-releases/release-details/release.injectable.ts b/src/renderer/components/+helm-releases/release-details/release.injectable.ts index 981ffce517..a4ca7f9c9a 100644 --- a/src/renderer/components/+helm-releases/release-details/release.injectable.ts +++ b/src/renderer/components/+helm-releases/release-details/release.injectable.ts @@ -20,7 +20,7 @@ const releaseInjectable = getInjectable({ const namespace = routeParameters.namespace.get(); if (!name || !namespace) { - return null; + return undefined; } return releases.value.get().find(matches({ name, namespace })); diff --git a/src/renderer/components/+helm-releases/release-menu.tsx b/src/renderer/components/+helm-releases/release-menu.tsx index a53c59a682..3bfffa69a4 100644 --- a/src/renderer/components/+helm-releases/release-menu.tsx +++ b/src/renderer/components/+helm-releases/release-menu.tsx @@ -4,17 +4,19 @@ */ import React from "react"; -import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api"; import { cssNames } from "../../utils"; import type { MenuActionsProps } from "../menu/menu-actions"; import { MenuActions } from "../menu/menu-actions"; import { MenuItem } from "../menu"; import { Icon } from "../icon"; import { withInjectables } from "@ogre-tools/injectable-react"; +import type { CreateUpgradeChartTab } from "../dock/upgrade-chart/create-upgrade-chart-tab.injectable"; import createUpgradeChartTabInjectable from "../dock/upgrade-chart/create-upgrade-chart-tab.injectable"; -import deleteReleaseInjectable from "./delete-release/delete-release.injectable"; import type { OpenHelmReleaseRollbackDialog } from "./dialog/open.injectable"; import openHelmReleaseRollbackDialogInjectable from "./dialog/open.injectable"; +import type { HelmRelease } from "../../k8s/helm-release"; +import type { DeleteHelmRelease } from "../../k8s/helm-releases.api/delete.injectable"; +import deleteHelmReleaseInjectable from "../../k8s/helm-releases.api/delete.injectable"; export interface HelmReleaseMenuProps extends MenuActionsProps { release: HelmRelease; @@ -22,14 +24,16 @@ export interface HelmReleaseMenuProps extends MenuActionsProps { } interface Dependencies { - deleteRelease: (release: HelmRelease) => Promise; - createUpgradeChartTab: (release: HelmRelease) => void; + deleteHelmRelease: DeleteHelmRelease; + createUpgradeChartTab: CreateUpgradeChartTab; openRollbackDialog: OpenHelmReleaseRollbackDialog; } class NonInjectedHelmReleaseMenu extends React.Component { - remove = () => { - return this.props.deleteRelease(this.props.release); + remove = async () => { + const { name, namespace } = this.props.release; + + await this.props.deleteHelmRelease(name, namespace); }; upgrade = () => { @@ -100,7 +104,7 @@ class NonInjectedHelmReleaseMenu extends React.Component(NonInjectedHelmReleaseMenu, { getProps: (di, props) => ({ ...props, - deleteRelease: di.inject(deleteReleaseInjectable), + deleteHelmRelease: di.inject(deleteHelmReleaseInjectable), createUpgradeChartTab: di.inject(createUpgradeChartTabInjectable), openRollbackDialog: di.inject(openHelmReleaseRollbackDialogInjectable), }), diff --git a/src/renderer/components/+helm-releases/releases.injectable.ts b/src/renderer/components/+helm-releases/releases.injectable.ts index e23640de6d..22d049f326 100644 --- a/src/renderer/components/+helm-releases/releases.injectable.ts +++ b/src/renderer/components/+helm-releases/releases.injectable.ts @@ -5,8 +5,8 @@ import { getInjectable } from "@ogre-tools/injectable"; import { asyncComputed } from "@ogre-tools/injectable-react"; import namespaceStoreInjectable from "../+namespaces/store.injectable"; -import { listReleases } from "../../../common/k8s-api/endpoints/helm-releases.api"; import clusterFrameContextInjectable from "../../cluster-frame-context/cluster-frame-context.injectable"; +import listHelmReleasesInjectable from "../../k8s/helm-releases.api/list.injectable"; import releaseSecretsInjectable from "./release-secrets.injectable"; const releasesInjectable = getInjectable({ @@ -16,6 +16,7 @@ const releasesInjectable = getInjectable({ const clusterContext = di.inject(clusterFrameContextInjectable); const namespaceStore = di.inject(namespaceStoreInjectable); const releaseSecrets = di.inject(releaseSecretsInjectable); + const listHelmReleases = di.inject(listHelmReleasesInjectable); return asyncComputed(async () => { const contextNamespaces = namespaceStore.contextNamespaces || []; @@ -29,11 +30,10 @@ const releasesInjectable = getInjectable({ contextNamespaces.includes(namespace), ); - const releaseArrays = await (isLoadingAll ? listReleases() : Promise.all( - contextNamespaces.map((namespace) => - listReleases(namespace), - ), - )); + const releaseArrays = await (isLoadingAll + ? listHelmReleases() + : Promise.all(contextNamespaces.map(listHelmReleases)) + ); return releaseArrays.flat(); }, []); diff --git a/src/renderer/components/+helm-releases/releases.tsx b/src/renderer/components/+helm-releases/releases.tsx index 38239e80c8..8d04d8e459 100644 --- a/src/renderer/components/+helm-releases/releases.tsx +++ b/src/renderer/components/+helm-releases/releases.tsx @@ -7,7 +7,6 @@ import "../item-object-list/item-list-layout.scss"; import "./releases.scss"; import React, { Component } from "react"; -import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api"; import { withInjectables } from "@ogre-tools/injectable-react"; import namespaceStoreInjectable from "../+namespaces/store.injectable"; import type { ItemListStore } from "../item-object-list"; @@ -17,14 +16,15 @@ import { kebabCase } from "lodash/fp"; import { HelmReleaseMenu } from "./release-menu"; import { ReleaseRollbackDialog } from "./dialog/dialog"; import { ReleaseDetails } from "./release-details/release-details"; +import type { RemovableHelmRelease } from "./removable-releases.injectable"; import removableReleasesInjectable from "./removable-releases.injectable"; -import type { RemovableHelmRelease } from "./removable-releases"; import type { IComputedValue } from "mobx"; import releasesInjectable from "./releases.injectable"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; import helmReleasesRouteParametersInjectable from "./helm-releases-route-parameters.injectable"; import type { NavigateToHelmReleases } from "../../../common/front-end-routing/routes/cluster/helm/releases/navigate-to-helm-releases.injectable"; import navigateToHelmReleasesInjectable from "../../../common/front-end-routing/routes/cluster/helm/releases/navigate-to-helm-releases.injectable"; +import type { HelmRelease } from "../../k8s/helm-release"; enum columnId { name = "name", diff --git a/src/renderer/components/+helm-releases/removable-releases.injectable.ts b/src/renderer/components/+helm-releases/removable-releases.injectable.ts index 5170bd3da3..e15456f00d 100644 --- a/src/renderer/components/+helm-releases/removable-releases.injectable.ts +++ b/src/renderer/components/+helm-releases/removable-releases.injectable.ts @@ -3,20 +3,47 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { observable } from "mobx"; +import { computed, observable } from "mobx"; +import type { HelmRelease } from "../../k8s/helm-release"; +import deleteHelmReleaseInjectable from "../../k8s/helm-releases.api/delete.injectable"; +import { toggle } from "../../utils"; import releasesInjectable from "./releases.injectable"; -import deleteReleaseInjectable from "./delete-release/delete-release.injectable"; -import { removableReleases } from "./removable-releases"; + +export interface RemovableHelmRelease extends HelmRelease { + toggle: () => void; + isSelected: boolean; + delete: () => Promise; +} const removableReleasesInjectable = getInjectable({ id: "removable-releases", - instantiate: (di) => - removableReleases({ - releases: di.inject(releasesInjectable), - deleteRelease: di.inject(deleteReleaseInjectable), - releaseSelectionStatus: observable.map(), - }), + instantiate: (di) => { + const releases = di.inject(releasesInjectable); + const deleteHelmRelease = di.inject(deleteHelmReleaseInjectable); + const selectedReleaseIds = observable.set(); + const isSelected = (release: HelmRelease) => selectedReleaseIds.has(release.getId()); + + return computed(() => + releases.value.get().map( + (release): RemovableHelmRelease => ({ + ...release, + + toggle: () => { + toggle(selectedReleaseIds, release.getId()); + }, + + get isSelected() { + return isSelected(release); + }, + + delete: async () => { + await deleteHelmRelease(release.name, release.namespace); + }, + }), + ), + ); + }, }); export default removableReleasesInjectable; diff --git a/src/renderer/components/+helm-releases/removable-releases.ts b/src/renderer/components/+helm-releases/removable-releases.ts deleted file mode 100644 index 0b5692a7d1..0000000000 --- a/src/renderer/components/+helm-releases/removable-releases.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { IAsyncComputed } from "@ogre-tools/injectable-react"; -import type { ObservableMap } from "mobx"; -import { computed } from "mobx"; -import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api"; - -interface Dependencies { - releases: IAsyncComputed; - releaseSelectionStatus: ObservableMap; - deleteRelease: (release: HelmRelease) => Promise; -} - -export interface RemovableHelmRelease extends HelmRelease { - toggle: () => void; - isSelected: boolean; - delete: () => Promise; -} - -export const removableReleases = ({ - releases, - releaseSelectionStatus, - deleteRelease, -}: Dependencies) => { - const isSelected = (release: HelmRelease) => - releaseSelectionStatus.get(release.getId()) || false; - - return computed(() => - releases.value.get().map( - (release): RemovableHelmRelease => ({ - ...release, - - toggle: () => { - releaseSelectionStatus.set(release.getId(), !isSelected(release)); - }, - - get isSelected() { - return isSelected(release); - }, - - delete: async () => { - await deleteRelease(release); - }, - }), - ), - ); -}; diff --git a/src/renderer/components/+helm-releases/rollback-release/rollback-release.injectable.ts b/src/renderer/components/+helm-releases/rollback-release/rollback-release.injectable.ts deleted file mode 100644 index c7ace21e06..0000000000 --- a/src/renderer/components/+helm-releases/rollback-release/rollback-release.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { rollbackRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import releasesInjectable from "../releases.injectable"; - -const rollbackReleaseInjectable = getInjectable({ - id: "rollback-release", - - instantiate: (di) => { - const releases = di.inject(releasesInjectable); - - return async (name: string, namespace: string, revision: number) => { - await rollbackRelease(name, namespace, revision); - - releases.invalidate(); - }; - }, -}); - -export default rollbackReleaseInjectable; diff --git a/src/renderer/components/+helm-releases/update-release/update-release.injectable.ts b/src/renderer/components/+helm-releases/update-release/update-release.injectable.ts deleted file mode 100644 index aa6aa9448d..0000000000 --- a/src/renderer/components/+helm-releases/update-release/update-release.injectable.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; - -import type { - HelmReleaseUpdatePayload } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { - updateRelease, -} from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import releasesInjectable from "../releases.injectable"; - -const updateReleaseInjectable = getInjectable({ - id: "update-release", - - instantiate: (di) => { - const releases = di.inject(releasesInjectable); - - return async ( - name: string, - namespace: string, - payload: HelmReleaseUpdatePayload, - ) => { - const result = await updateRelease(name, namespace, payload); - - releases.invalidate(); - - return result; - }; - }, -}); - -export default updateReleaseInjectable; diff --git a/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts b/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts index 29e94ebfc6..9b9d529d1a 100644 --- a/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts +++ b/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import installChartTabStoreInjectable from "./store.injectable"; -import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; +import type { HelmChart } from "../../../k8s/helm-chart"; import type { DockTab, DockTabCreateSpecific } from "../dock/store"; import { TabKind } from "../dock/store"; import createDockTabInjectable from "../dock/create-dock-tab.injectable"; diff --git a/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx b/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx index 64f2e27e12..8a25cebe48 100644 --- a/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx +++ b/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx @@ -8,7 +8,6 @@ import { waitUntilDefined } from "../../../../common/utils"; import type { CallForHelmChartValues } from "./chart-data/call-for-helm-chart-values.injectable"; import callForHelmChartValuesInjectable from "./chart-data/call-for-helm-chart-values.injectable"; import type { IChartInstallData, InstallChartTabStore } from "./store"; -import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; import React from "react"; import { action, @@ -19,13 +18,14 @@ import { import assert from "assert"; import type { CallForCreateHelmRelease } from "../../+helm-releases/create-release/call-for-create-helm-release.injectable"; import callForCreateHelmReleaseInjectable from "../../+helm-releases/create-release/call-for-create-helm-release.injectable"; -import type { HelmReleaseUpdateDetails } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import dockStoreInjectable from "../dock/store.injectable"; import type { NavigateToHelmReleases } from "../../../../common/front-end-routing/routes/cluster/helm/releases/navigate-to-helm-releases.injectable"; import navigateToHelmReleasesInjectable from "../../../../common/front-end-routing/routes/cluster/helm/releases/navigate-to-helm-releases.injectable"; import type { SingleValue } from "react-select"; import type { CallForHelmChartVersions } from "../../+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; import callForHelmChartVersionsInjectable from "../../+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; +import type { HelmChart } from "../../../k8s/helm-chart"; +import type { HelmReleaseUpdateDetails } from "../../../k8s/helm-releases.api/update.injectable"; const installChartModelInjectable = getInjectable({ id: "install-chart-model", diff --git a/src/renderer/components/dock/install-chart/store.injectable.ts b/src/renderer/components/dock/install-chart/store.injectable.ts index 9d0250ab8f..8563be8598 100644 --- a/src/renderer/components/dock/install-chart/store.injectable.ts +++ b/src/renderer/components/dock/install-chart/store.injectable.ts @@ -5,8 +5,10 @@ import { getInjectable } from "@ogre-tools/injectable"; import { InstallChartTabStore } from "./store"; import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable"; -import type { HelmReleaseUpdateDetails } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; +import type { HelmReleaseUpdateDetails } from "../../../k8s/helm-releases.api/update.injectable"; +import getHelmChartDetailsInjectable from "../../../k8s/helm-charts.api/get-details.injectable"; +import getHelmChartValuesInjectable from "../../../k8s/helm-charts.api/get-values.injectable"; const installChartTabStoreInjectable = getInjectable({ id: "install-chart-tab-store", @@ -18,6 +20,8 @@ const installChartTabStoreInjectable = getInjectable({ createStorage: di.inject(createStorageInjectable), versionsStore: createDockTabStore(), detailsStore: createDockTabStore(), + getHelmChartDetails: di.inject(getHelmChartDetailsInjectable), + getHelmChartValues: di.inject(getHelmChartValuesInjectable), }); }, }); diff --git a/src/renderer/components/dock/install-chart/store.ts b/src/renderer/components/dock/install-chart/store.ts index 7bb7b3bfcc..22012c6784 100644 --- a/src/renderer/components/dock/install-chart/store.ts +++ b/src/renderer/components/dock/install-chart/store.ts @@ -4,9 +4,9 @@ */ import { makeObservable } from "mobx"; +import type { HelmReleaseUpdateDetails } from "../../../k8s/helm-releases.api/update.injectable"; import type { DockTabStoreDependencies } from "../dock-tab-store/dock-tab.store"; import { DockTabStore } from "../dock-tab-store/dock-tab.store"; -import type { HelmReleaseUpdateDetails } from "../../../../common/k8s-api/endpoints/helm-releases.api"; export interface IChartInstallData { name: string; diff --git a/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts b/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts index 014e46760f..6701191a3e 100644 --- a/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts +++ b/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts @@ -5,53 +5,49 @@ import { getInjectable } from "@ogre-tools/injectable"; import upgradeChartTabStoreInjectable from "./store.injectable"; import dockStoreInjectable from "../dock/store.injectable"; -import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import type { DockStore, DockTabCreateSpecific, TabId } from "../dock/store"; +import type { DockTabCreateSpecific, TabId } from "../dock/store"; import { TabKind } from "../dock/store"; -import type { UpgradeChartTabStore } from "./store"; import { runInAction } from "mobx"; +import type { HelmRelease } from "../../../k8s/helm-release"; -interface Dependencies { - upgradeChartStore: UpgradeChartTabStore; - dockStore: DockStore; -} - -const createUpgradeChartTab = ({ upgradeChartStore, dockStore }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateSpecific = {}): TabId => { - const tabId = upgradeChartStore.getTabIdByRelease(release.getName()); - - if (tabId) { - dockStore.open(); - dockStore.selectTab(tabId); - - return tabId; - } - - return runInAction(() => { - const tab = dockStore.createTab( - { - title: `Helm Upgrade: ${release.getName()}`, - ...tabParams, - kind: TabKind.UPGRADE_CHART, - }, - false, - ); - - upgradeChartStore.setData(tab.id, { - releaseName: release.getName(), - releaseNamespace: release.getNs(), - }); - - return tab.id; - }); -}; +export type CreateUpgradeChartTab = (release: HelmRelease, tabParams?: DockTabCreateSpecific) => TabId; const createUpgradeChartTabInjectable = getInjectable({ id: "create-upgrade-chart-tab", - instantiate: (di) => createUpgradeChartTab({ - upgradeChartStore: di.inject(upgradeChartTabStoreInjectable), - dockStore: di.inject(dockStoreInjectable), - }), + instantiate: (di): CreateUpgradeChartTab => { + const dockStore = di.inject(dockStoreInjectable); + const upgradeChartStore = di.inject(upgradeChartTabStoreInjectable); + + return (release, tabParams = {}) => { + const tabId = upgradeChartStore.getTabIdByRelease(release.getName()); + + if (tabId) { + dockStore.open(); + dockStore.selectTab(tabId); + + return tabId; + } + + return runInAction(() => { + const tab = dockStore.createTab( + { + title: `Helm Upgrade: ${release.getName()}`, + ...tabParams, + kind: TabKind.UPGRADE_CHART, + }, + false, + ); + + upgradeChartStore.setData(tab.id, { + releaseName: release.getName(), + releaseNamespace: release.getNs(), + }); + + return tab.id; + }); + }; + }, }); export default createUpgradeChartTabInjectable; diff --git a/src/renderer/components/dock/upgrade-chart/store.injectable.ts b/src/renderer/components/dock/upgrade-chart/store.injectable.ts index 29a53c41d3..b42c0b0408 100644 --- a/src/renderer/components/dock/upgrade-chart/store.injectable.ts +++ b/src/renderer/components/dock/upgrade-chart/store.injectable.ts @@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { UpgradeChartTabStore } from "./store"; import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; +import getHelmReleaseValuesInjectable from "../../../k8s/helm-releases.api/get-values.injectable"; const upgradeChartTabStoreInjectable = getInjectable({ id: "upgrade-chart-tab-store", @@ -16,6 +17,7 @@ const upgradeChartTabStoreInjectable = getInjectable({ return new UpgradeChartTabStore({ createStorage: di.inject(createStorageInjectable), valuesStore: createDockTabStore(), + getHelmReleaseValues: di.inject(getHelmReleaseValuesInjectable), }); }, }); diff --git a/src/renderer/components/dock/upgrade-chart/store.ts b/src/renderer/components/dock/upgrade-chart/store.ts index 3e699c01b1..2de469d5b2 100644 --- a/src/renderer/components/dock/upgrade-chart/store.ts +++ b/src/renderer/components/dock/upgrade-chart/store.ts @@ -7,8 +7,8 @@ import { action, computed, makeObservable } from "mobx"; import type { TabId } from "../dock/store"; import type { DockTabStoreDependencies } from "../dock-tab-store/dock-tab.store"; import { DockTabStore } from "../dock-tab-store/dock-tab.store"; -import { getReleaseValues } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import assert from "assert"; +import type { GetHelmReleaseValues } from "../../../k8s/helm-releases.api/get-values.injectable"; export interface IChartUpgradeData { releaseName: string; @@ -17,6 +17,7 @@ export interface IChartUpgradeData { export interface UpgradeChartTabStoreDependencies extends DockTabStoreDependencies { valuesStore: DockTabStore; + getHelmReleaseValues: GetHelmReleaseValues; } export class UpgradeChartTabStore extends DockTabStore { @@ -44,7 +45,7 @@ export class UpgradeChartTabStore extends DockTabStore { assert(data, "cannot reload values if no data"); const { releaseName, releaseNamespace } = data; - const values = await getReleaseValues(releaseName, releaseNamespace, true); + const values = await this.dependencies.getHelmReleaseValues(releaseName, releaseNamespace, true); this.values.setData(tabId, values); } diff --git a/src/renderer/components/dock/upgrade-chart/view.tsx b/src/renderer/components/dock/upgrade-chart/view.tsx index 9dc9d4ed4a..b9e23e9ec9 100644 --- a/src/renderer/components/dock/upgrade-chart/view.tsx +++ b/src/renderer/components/dock/upgrade-chart/view.tsx @@ -15,15 +15,17 @@ import type { UpgradeChartTabStore } from "./store"; import { Spinner } from "../../spinner"; import { Badge } from "../../badge"; import { EditorPanel } from "../editor-panel"; -import { helmChartStore, type ChartVersion } from "../../+helm-charts/helm-chart.store"; -import type { HelmRelease, HelmReleaseUpdateDetails, HelmReleaseUpdatePayload } from "../../../../common/k8s-api/endpoints/helm-releases.api"; +import type { ChartVersion, HelmChartStore } from "../../+helm-charts/store"; import type { SelectOption } from "../../select"; import { Select } from "../../select"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import upgradeChartTabStoreInjectable from "./store.injectable"; -import updateReleaseInjectable from "../../+helm-releases/update-release/update-release.injectable"; import releasesInjectable from "../../+helm-releases/releases.injectable"; +import helmChartStoreInjectable from "../../+helm-charts/store.injectable"; +import type { HelmRelease } from "../../../k8s/helm-release"; +import type { UpdateHelmRelease } from "../../../k8s/helm-releases.api/update.injectable"; +import updateHelmReleaseInjectable from "../../../k8s/helm-releases.api/update.injectable"; export interface UpgradeChartProps { className?: string; @@ -33,7 +35,8 @@ export interface UpgradeChartProps { interface Dependencies { releases: IAsyncComputed; upgradeChartTabStore: UpgradeChartTabStore; - updateRelease: (name: string, namespace: string, payload: HelmReleaseUpdatePayload) => Promise; + updateHelmRelease: UpdateHelmRelease; + helmChartStore: HelmChartStore; } @observer @@ -93,7 +96,7 @@ export class NonInjectedUpgradeChart extends React.Component(NonInjectedUpgradeChart, { getProps: (di, props) => ({ - releases: di.inject(releasesInjectable), - updateRelease: di.inject(updateReleaseInjectable), - upgradeChartTabStore: di.inject(upgradeChartTabStoreInjectable), ...props, + releases: di.inject(releasesInjectable), + updateHelmRelease: di.inject(updateHelmReleaseInjectable), + upgradeChartTabStore: di.inject(upgradeChartTabStoreInjectable), + helmChartStore: di.inject(helmChartStoreInjectable), }), }); diff --git a/src/renderer/getDiForUnitTesting.tsx b/src/renderer/getDiForUnitTesting.tsx index bf6c1167a5..d9486134dd 100644 --- a/src/renderer/getDiForUnitTesting.tsx +++ b/src/renderer/getDiForUnitTesting.tsx @@ -73,6 +73,8 @@ import forceUpdateModalRootFrameComponentInjectable from "./application-update/f import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable"; import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable"; import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable"; +import isProductionInjectable from "../common/vars/is-production.injectable"; +import isDebuggingInjectable from "../common/vars/is-debugging.injectable"; export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => { const { @@ -208,6 +210,8 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) overrideFsWithFakes(di); di.override(focusWindowInjectable, () => () => {}); + di.override(isProductionInjectable, () => true); + di.override(isDebuggingInjectable, () => false); di.override(loggerInjectable, () => ({ warn: noop, diff --git a/src/common/k8s-api/endpoints/helm-charts.api.ts b/src/renderer/k8s/helm-chart.ts similarity index 68% rename from src/common/k8s-api/endpoints/helm-charts.api.ts rename to src/renderer/k8s/helm-chart.ts index f4ba0cf45f..f1580a617b 100644 --- a/src/common/k8s-api/endpoints/helm-charts.api.ts +++ b/src/renderer/k8s/helm-chart.ts @@ -3,95 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { compile } from "path-to-regexp"; -import { apiBase } from "../index"; -import { stringify } from "querystring"; -import type { RequestInit } from "node-fetch"; -import { autoBind, bifurcateArray, isDefined } from "../../utils"; import Joi from "joi"; - -export type RepoHelmChartList = Record; - -export interface IHelmChartDetails { - readme: string; - versions: HelmChart[]; -} - -const endpoint = compile(`/v2/charts/:repo?/:name?`) as (params?: { - repo?: string; - name?: string; -}) => string; - -/** - * Get a list of all helm charts from all saved helm repos - */ -export async function listCharts(): Promise { - const data = await apiBase.get>(endpoint()); - - return Object - .values(data) - .reduce((allCharts, repoCharts) => allCharts.concat(Object.values(repoCharts)), new Array()) - .map(([chart]) => HelmChart.create(chart, { onError: "log" })) - .filter(isDefined); -} - -export interface GetChartDetailsOptions { - version?: string; - reqInit?: RequestInit; -} - -/** - * Get the readme and all versions of a chart - * @param repo The repo to get from - * @param name The name of the chart to request the data of - * @param options.version The version of the chart's readme to get, default latest - * @param options.reqInit A way for passing in an abort controller or other browser request options - */ -export async function getChartDetails(repo: string, name: string, { version, reqInit }: GetChartDetailsOptions = {}): Promise { - const path = endpoint({ repo, name }); - - const { readme, ...data } = await apiBase.get(`${path}?${stringify({ version })}`, undefined, reqInit); - const versions = data.versions.map(version => HelmChart.create(version, { onError: "log" })).filter(isDefined); - - return { - readme, - versions, - }; -} - -/** - * Get chart values related to a specific repos' version of a chart - * @param repo The repo to get from - * @param name The name of the chart to request the data of - * @param version The version to get the values from - */ -export async function getChartValues(repo: string, name: string, version: string): Promise { - 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; -} +import type { HelmChartMaintainer, RawHelmChart, RawHelmChartDependency } from "../../common/helm/chart"; +import { autoBind, bifurcateArray } from "../utils"; const helmChartMaintainerValidator = Joi.object({ name: Joi @@ -225,20 +139,6 @@ 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; diff --git a/src/renderer/k8s/helm-charts.api/get-details.injectable.ts b/src/renderer/k8s/helm-charts.api/get-details.injectable.ts new file mode 100644 index 0000000000..9a8f34dacc --- /dev/null +++ b/src/renderer/k8s/helm-charts.api/get-details.injectable.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { isDefined } from "../../../common/utils"; +import { stringify } from "querystring"; +import type { RequestInit } from "node-fetch"; +import { HelmChart } from "../helm-chart"; +import apiBaseInjectable from "../api-base.injectable"; + +export interface HelmChartDetails { + readme: string; + versions: HelmChart[]; +} + +export interface GetChartDetailsOptions { + version?: string; + reqInit?: RequestInit; +} + +/** + * Get the readme and all versions of a chart + * @param repo The repo to get from + * @param name The name of the chart to request the data of + * @param options.version The version of the chart's readme to get, default latest + * @param options.reqInit A way for passing in an abort controller or other browser request options + */ +export type GetHelmChartDetails = (repo: string, name: string, opts?: GetChartDetailsOptions) => Promise; + +const getHelmChartDetailsInjectable = getInjectable({ + id: "get-helm-chart-details", + instantiate: (di): GetHelmChartDetails => { + const apiBase = di.inject(apiBaseInjectable); + + return async (repo, name, { version, reqInit } = {}) => { + const { readme, versions: rawVersions } = await apiBase.get(`/v2/charts/${repo}/${name}?${stringify({ version })}`, undefined, reqInit) as HelmChartDetails; + const versions = rawVersions + .map(version => HelmChart.create(version, { onError: "log" })) + .filter(isDefined); + + return { + readme, + versions, + }; + }; + }, +}); + +export default getHelmChartDetailsInjectable; diff --git a/src/renderer/k8s/helm-charts.api/get-values.injectable.ts b/src/renderer/k8s/helm-charts.api/get-values.injectable.ts new file mode 100644 index 0000000000..a1b8606215 --- /dev/null +++ b/src/renderer/k8s/helm-charts.api/get-values.injectable.ts @@ -0,0 +1,26 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { stringify } from "querystring"; +import apiBaseInjectable from "../api-base.injectable"; + +/** + * Get chart values related to a specific repos' version of a chart + * @param repo The repo to get from + * @param name The name of the chart to request the data of + * @param version The version to get the values from + */ +export type GetHelmChartValues = (repo: string, name: string, version: string) => Promise; + +const getHelmChartValuesInjectable = getInjectable({ + id: "get-helm-chart-values", + instantiate: (di): GetHelmChartValues => { + const apiBase = di.inject(apiBaseInjectable); + + return (repo, name, version) => apiBase.get(`/v2/charts/${repo}/${name}/values?${stringify({ version })}`); + }, +}); + +export default getHelmChartValuesInjectable; diff --git a/src/renderer/k8s/helm-charts.api/list.injectable.ts b/src/renderer/k8s/helm-charts.api/list.injectable.ts new file mode 100644 index 0000000000..c885381e2b --- /dev/null +++ b/src/renderer/k8s/helm-charts.api/list.injectable.ts @@ -0,0 +1,33 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { RawHelmChart, RepoHelmChartList } from "../../../common/helm/chart"; +import { isDefined } from "../../../common/utils"; +import apiBaseInjectable from "../api-base.injectable"; +import { HelmChart } from "../helm-chart"; + +/** + * Get a list of all helm charts from all saved helm repos + */ +export type ListHelmCharts = () => Promise; + +const listHelmChartsInjectable = getInjectable({ + id: "list-helm-charts", + instantiate: (di): ListHelmCharts => { + const apiBase = di.inject(apiBaseInjectable); + + return async () => { + const data = await apiBase.get>("/v2/charts"); + + return Object + .values(data) + .reduce((allCharts, repoCharts) => allCharts.concat(Object.values(repoCharts)), new Array()) + .map(([chart]) => HelmChart.create(chart, { onError: "log" })) + .filter(isDefined); + }; + }, +}); + +export default listHelmChartsInjectable; diff --git a/src/renderer/k8s/helm-release.ts b/src/renderer/k8s/helm-release.ts new file mode 100644 index 0000000000..0928439abe --- /dev/null +++ b/src/renderer/k8s/helm-release.ts @@ -0,0 +1,26 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { ItemObject } from "../../common/item.store"; + +export interface RawHelmRelease { + appVersion: string; + name: string; + namespace: string; + chart: string; + status: string; + updated: string; + revision: string; +} + +export interface HelmRelease extends RawHelmRelease, ItemObject { + getNs: () => string; + getChart: (withVersion?: boolean) => string; + getRevision: () => number; + getStatus: () => string; + getVersion: () => string; + getUpdated: (humanize?: boolean, compact?: boolean) => string | number; + getRepo: () => Promise; +} diff --git a/src/renderer/k8s/helm-releases.api.ts b/src/renderer/k8s/helm-releases.api.ts new file mode 100644 index 0000000000..859e8ae6f9 --- /dev/null +++ b/src/renderer/k8s/helm-releases.api.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { KubeJsonApiData } from "../../common/k8s-api/kube-json-api"; +import { buildURLPositional } from "../../common/utils/buildUrl"; + +export interface HelmReleaseDetails { + resources: KubeJsonApiData[]; + name: string; + namespace: string; + version: string; + config: string; // release values + manifest: string; + info: { + deleted: string; + description: string; + first_deployed: string; + last_deployed: string; + notes: string; + status: string; + }; +} + +type EndpointParams = {} + | { namespace: string } + | { namespace: string; name: string }; + +export const helmReleasesUrl = buildURLPositional("/v2/releases/:namespace?/:name?"); + diff --git a/src/renderer/k8s/helm-releases.api/create.injectable.ts b/src/renderer/k8s/helm-releases.api/create.injectable.ts new file mode 100644 index 0000000000..7c5092464d --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/create.injectable.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { load } from "js-yaml"; +import releasesInjectable from "../../components/+helm-releases/releases.injectable"; +import apiBaseInjectable from "../api-base.injectable"; +import type { HelmReleaseDetails } from "../helm-releases.api"; +import { helmReleasesUrl } from "../helm-releases.api"; + + +export interface HelmReleaseCreateDetails { + log: string; + release: HelmReleaseDetails; +} +export interface HelmReleaseCreatePayload { + name?: string; + repo: string; + chart: string; + namespace: string; + version: string; + values: string; +} +export type CreateHelmRelease = (payload: HelmReleaseCreatePayload) => Promise; + +const createHelmReleaseInjectable = getInjectable({ + id: "create-helm-release", + instantiate: (di): CreateHelmRelease => { + const apiBase = di.inject(apiBaseInjectable); + const releases = di.inject(releasesInjectable); + + return async ({ repo, chart, values, ...data }) => { + const result = await apiBase.post(helmReleasesUrl(), { + data: { + chart: `${repo}/${chart}`, + values: load(values), + ...data, + }, + }) as HelmReleaseCreateDetails; + + releases.invalidate(); + + return result; + }; + }, +}); + +export default createHelmReleaseInjectable; diff --git a/src/renderer/k8s/helm-releases.api/delete.injectable.ts b/src/renderer/k8s/helm-releases.api/delete.injectable.ts new file mode 100644 index 0000000000..698b6fb09e --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/delete.injectable.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { JsonApiData } from "../../../common/k8s-api/json-api"; +import releasesInjectable from "../../components/+helm-releases/releases.injectable"; +import apiBaseInjectable from "../api-base.injectable"; +import { helmReleasesUrl } from "../helm-releases.api"; + +export type DeleteHelmRelease = (name: string, namespace: string) => Promise; + +const deleteHelmReleaseInjectable = getInjectable({ + id: "delete-helm-release", + instantiate: (di): DeleteHelmRelease => { + const apiBase = di.inject(apiBaseInjectable); + const releases = di.inject(releasesInjectable); + + return async (name, namespace) => { + const result = await apiBase.del(helmReleasesUrl({ name, namespace })); + + releases.invalidate(); + + return result; + }; + }, +}); + +export default deleteHelmReleaseInjectable; diff --git a/src/renderer/k8s/helm-releases.api/get-details.injectable.ts b/src/renderer/k8s/helm-releases.api/get-details.injectable.ts new file mode 100644 index 0000000000..b6843470ad --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/get-details.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import apiBaseInjectable from "../api-base.injectable"; +import type { HelmReleaseDetails } from "../helm-releases.api"; +import { helmReleasesUrl } from "../helm-releases.api"; + +export type GetHelmReleaseDetails = (name: string, namespace: string) => Promise; + +const getHelmReleaseDetailsInjectable = getInjectable({ + id: "get-helm-release-details", + instantiate: (di): GetHelmReleaseDetails => { + const apiBase = di.inject(apiBaseInjectable); + + return (name, namespace) => apiBase.get(helmReleasesUrl({ name, namespace })); + }, +}); + +export default getHelmReleaseDetailsInjectable; diff --git a/src/renderer/k8s/helm-releases.api/get-history.injectable.ts b/src/renderer/k8s/helm-releases.api/get-history.injectable.ts new file mode 100644 index 0000000000..d1953f61f8 --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/get-history.injectable.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { buildURLPositional } from "../../../common/utils/buildUrl"; +import apiBaseInjectable from "../api-base.injectable"; + +export interface HelmReleaseRevision { + revision: number; + updated: string; + status: string; + chart: string; + app_version: string; + description: string; +} + +export type GetHelmReleaseHistory = (name: string, namespace: string) => Promise; + +const getHelmReleaseHistoryUrl = buildURLPositional<{ namespace: string; name: string }>("/v2/releases/:namespace/:name/history"); + +const getHelmReleaseHistoryInjectable = getInjectable({ + id: "get-helm-release-history", + instantiate: (di): GetHelmReleaseHistory => { + const apiBase = di.inject(apiBaseInjectable); + + return (name, namespace) => apiBase.get(getHelmReleaseHistoryUrl({ name, namespace })); + }, +}); + +export default getHelmReleaseHistoryInjectable; diff --git a/src/renderer/k8s/helm-releases.api/get-values.injectable.ts b/src/renderer/k8s/helm-releases.api/get-values.injectable.ts new file mode 100644 index 0000000000..2be86a8874 --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/get-values.injectable.ts @@ -0,0 +1,28 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { buildURLPositional } from "../../../common/utils/buildUrl"; +import apiBaseInjectable from "../api-base.injectable"; + +export type GetHelmReleaseValues = (name: string, namespace: string, all?: boolean) => Promise; + +const getHelmReleaseValuesUrl = buildURLPositional< + { namespace: string; name: string }, + { all?: boolean } +>("/v2/releases/:namespace/:name/values"); + +const getHelmReleaseValuesInjectable = getInjectable({ + id: "get-helm-release-values", + instantiate: (di): GetHelmReleaseValues => { + const apiBase = di.inject(apiBaseInjectable); + + return (name, namespace, all) => apiBase.get(getHelmReleaseValuesUrl( + { name, namespace }, + { all }, + )); + }, +}); + +export default getHelmReleaseValuesInjectable; diff --git a/src/renderer/k8s/helm-releases.api/list.injectable.ts b/src/renderer/k8s/helm-releases.api/list.injectable.ts new file mode 100644 index 0000000000..3d4a17210e --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/list.injectable.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import apiBaseInjectable from "../api-base.injectable"; +import type { HelmRelease, RawHelmRelease } from "../helm-release"; +import { helmReleasesUrl } from "../helm-releases.api"; +import toHelmReleaseInjectable from "./to-instance.injectable"; + +export type ListHelmReleases = (namespace?: string) => Promise; + +const listHelmReleasesInjectable = getInjectable({ + id: "list-helm-releases", + instantiate: (di): ListHelmReleases => { + const apiBase = di.inject(apiBaseInjectable); + const toHelmRelease = di.inject(toHelmReleaseInjectable); + + return async (namespace) => { + const releases = await apiBase.get(helmReleasesUrl({ namespace })); + + return releases.map(toHelmRelease); + }; + }, +}); + +export default listHelmReleasesInjectable; diff --git a/src/renderer/k8s/helm-releases.api/rollback.injectable.ts b/src/renderer/k8s/helm-releases.api/rollback.injectable.ts new file mode 100644 index 0000000000..7bcca772f1 --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/rollback.injectable.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { JsonApiData } from "../../../common/k8s-api/json-api"; +import { buildURLPositional } from "../../../common/utils/buildUrl"; +import releasesInjectable from "../../components/+helm-releases/releases.injectable"; +import apiBaseInjectable from "../api-base.injectable"; + +export type RollbackHelmRelease = (name: string, namespace: string, revision: number) => Promise; + +const rollbackHelmReleaseUrl = buildURLPositional<{ namespace: string; name: string }>("/v2/releases/:namespace/:name/rollback"); + +const rollbackHelmReleaseInjectable = getInjectable({ + id: "rollback-helm-release", + instantiate: (di): RollbackHelmRelease => { + const apiBase = di.inject(apiBaseInjectable); + const releases = di.inject(releasesInjectable); + + return async (name, namespace, revision) => { + const result = await apiBase.put( + rollbackHelmReleaseUrl({ name, namespace }), + { data: { revision }}, + ); + + releases.invalidate(); + + return result; + }; + }, +}); + +export default rollbackHelmReleaseInjectable; diff --git a/src/renderer/k8s/helm-releases.api/to-instance.injectable.ts b/src/renderer/k8s/helm-releases.api/to-instance.injectable.ts new file mode 100644 index 0000000000..5beebd9612 --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/to-instance.injectable.ts @@ -0,0 +1,87 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { capitalize } from "lodash/fp"; +import helmChartStoreInjectable from "../../components/+helm-charts/store.injectable"; +import { formatDuration } from "../../utils"; +import type { HelmRelease, RawHelmRelease } from "../helm-release"; + +export type ToHelmRelease = (raw: RawHelmRelease) => HelmRelease; + +const toHelmReleaseInjectable = getInjectable({ + id: "to-helm-release", + instantiate: (di): ToHelmRelease => { + const helmChartStore = di.inject(helmChartStoreInjectable); + + return (release) => ({ + ...release, + + getId() { + return this.namespace + this.name; + }, + + getName() { + return this.name; + }, + + getNs() { + return this.namespace; + }, + + getChart(withVersion = false) { + let chart = this.chart; + + if (!withVersion && this.getVersion() != "") { + const search = new RegExp(`-${this.getVersion()}`); + + chart = chart.replace(search, ""); + } + + return chart; + }, + + getRevision() { + return parseInt(this.revision, 10); + }, + + getStatus() { + return capitalize(this.status); + }, + + getVersion() { + const versions = this.chart.match(/(?<=-)(v?\d+)[^-].*$/); + + return versions?.[0] ?? ""; + }, + + getUpdated(humanize = true, compact = true) { + const updated = this.updated.replace(/\s\w*$/, ""); // 2019-11-26 10:58:09 +0300 MSK -> 2019-11-26 10:58:09 +0300 to pass into Date() + const updatedDate = new Date(updated).getTime(); + const diff = Date.now() - updatedDate; + + if (humanize) { + return formatDuration(diff, compact); + } + + return diff; + }, + + // Helm does not store from what repository the release is installed, + // so we have to try to guess it by searching charts + async getRepo() { + const chartName = this.getChart(); + const version = this.getVersion(); + const versions = await helmChartStore.getVersions(chartName); + const chartVersion = versions.find( + (chartVersion) => chartVersion.version === version, + ); + + return chartVersion ? chartVersion.repo : ""; + }, + }); + }, +}); + +export default toHelmReleaseInjectable; diff --git a/src/renderer/k8s/helm-releases.api/update.injectable.ts b/src/renderer/k8s/helm-releases.api/update.injectable.ts new file mode 100644 index 0000000000..8acafbef1c --- /dev/null +++ b/src/renderer/k8s/helm-releases.api/update.injectable.ts @@ -0,0 +1,48 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { load } from "js-yaml"; +import releasesInjectable from "../../components/+helm-releases/releases.injectable"; +import apiBaseInjectable from "../api-base.injectable"; +import type { HelmReleaseDetails } from "../helm-releases.api"; +import { helmReleasesUrl } from "../helm-releases.api"; + +export interface HelmReleaseUpdatePayload { + repo: string; + chart: string; + version: string; + values: string; +} + +export interface HelmReleaseUpdateDetails { + log: string; + release: HelmReleaseDetails; +} + +export type UpdateHelmRelease = (name: string, namespace: string, payload: HelmReleaseUpdatePayload) => Promise; + +const updateHelmReleaseInjectable = getInjectable({ + id: "update-helm-release", + instantiate: (di): UpdateHelmRelease => { + const apiBase = di.inject(apiBaseInjectable); + const releases = di.inject(releasesInjectable); + + return async (name, namespace, { repo, chart, values, ...data }) => { + const result = await apiBase.put(helmReleasesUrl({ name, namespace }), { + data: { + chart: `${repo}/${chart}`, + values: load(values), + ...data, + }, + }) as HelmReleaseUpdateDetails; + + releases.invalidate(); + + return result; + }; + }, +}); + +export default updateHelmReleaseInjectable;