diff --git a/src/behaviours/helm-charts/__snapshots__/listing-active-helm-repositories-in-preferences.test.ts.snap b/src/behaviours/helm-charts/__snapshots__/listing-active-helm-repositories-in-preferences.test.ts.snap new file mode 100644 index 0000000000..c225666a26 --- /dev/null +++ b/src/behaviours/helm-charts/__snapshots__/listing-active-helm-repositories-in-preferences.test.ts.snap @@ -0,0 +1,3343 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories when configuration resolves renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories when configuration resolves when updating repositories resolve when loading repositories resolves with existing repositories renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ some-repository +
+
+ some-repository-url +
+
+
+
+ some-other-repository +
+
+ some-other-repository-url +
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories when configuration resolves when updating repositories resolve when loading repositories resolves with no existing repositories renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories when configuration resolves when updating repositories resolve when loading repositories resolves with no existing repositories when adding of default repository resolves renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories when configuration resolves without path to repository cache directory renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ The repositories have not been added yet +
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; + +exports[`listing active helm repositories in preferences when navigating to preferences containing helm repositories when configuration resolves without path to repository config file renders 1`] = ` + +
+
+ +
+
+
+
+

+ Kubernetes +

+
+
+ Kubectl binary download + +
+ +
+
+
+ Download mirror + +
+
+ + +
+
+
+ Download mirror for kubectl +
+
+ +
+
+
+ + +
+
+
+
+
+
+ Directory for binaries + +
+
+ +
+
+
+ The directory to download binaries into. +
+
+
+
+ Path to kubectl binary + +
+
+ +
+
+
+
+
+
+

+ Kubeconfig Syncs +

+
+ +
+
+ Synced Items + +
+
+
+ No files and folders have been synced yet +
+
+
+
+
+

+ Helm Charts +

+
+
+
+ + +
+
+
+ Repositories +
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ The repositories have not been added yet +
+
+
+
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+ +`; diff --git a/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts new file mode 100644 index 0000000000..711acf67e6 --- /dev/null +++ b/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -0,0 +1,378 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RenderResult } from "@testing-library/react"; +import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ReadYamlFile } from "../../common/fs/read-yaml-file.injectable"; +import readYamlFileInjectable from "../../common/fs/read-yaml-file.injectable"; +import type { AsyncFnMock } from "@async-fn/jest"; +import asyncFn from "@async-fn/jest"; +import type { HelmRepositoriesFromYaml } from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; +import execFileInjectable from "../../common/fs/exec-file.injectable"; +import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; +import loggerInjectable from "../../common/logger.injectable"; +import type { Logger } from "../../common/logger"; + +describe("listing active helm repositories in preferences", () => { + let applicationBuilder: ApplicationBuilder; + let rendered: RenderResult; + let readYamlFileMock: AsyncFnMock; + let execFileMock: AsyncFnMock>; + let loggerStub: Logger; + + beforeEach(async () => { + applicationBuilder = getApplicationBuilder(); + + readYamlFileMock = asyncFn(); + execFileMock = asyncFn(); + + loggerStub = { warn: jest.fn() } as unknown as Logger; + + applicationBuilder.beforeApplicationStart(({ mainDi }) => { + mainDi.override(readYamlFileInjectable, () => readYamlFileMock); + mainDi.override(execFileInjectable, () => execFileMock); + mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path"); + mainDi.override(loggerInjectable, () => loggerStub); + }); + + rendered = await applicationBuilder.render(); + }); + + describe("when navigating to preferences containing helm repositories", () => { + beforeEach(async () => { + applicationBuilder.preferences.navigate(); + applicationBuilder.preferences.navigation.click("kubernetes"); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("shows loader for repositories", () => { + expect( + rendered.getByTestId("helm-repositories-are-loading"), + ).toBeInTheDocument(); + }); + + it("calls for helm configuration", () => { + expect(execFileMock).toHaveBeenCalledWith( + "some-helm-binary-path", + ["env"], + ); + }); + + it("does not call for updating of repositories yet", () => { + expect(execFileMock).not.toHaveBeenCalledWith( + "some-helm-binary-path", + ["repo", "update"], + ); + }); + + describe("when configuration resolves without path to repository config file", () => { + beforeEach(async () => { + execFileMock.mockClear(); + + await execFileMock.resolveSpecific( + ["some-helm-binary-path", ["env"]], + "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("logs error", () => { + expect(loggerStub.warn).toHaveBeenCalledWith( + "Tried to get Helm repositories, but HELM_REPOSITORY_CONFIG was not present in `$ helm env`. Behaving as if there were no repositories.", + ); + }); + + it("shows message about no repositories found", () => { + expect( + rendered.getByTestId("no-helm-repositories"), + ).toBeInTheDocument(); + }); + + it("does not show loader for repositories anymore", () => { + expect( + rendered.queryByTestId("helm-repositories-are-loading"), + ).not.toBeInTheDocument(); + }); + + it("does not call for updating of repositories", () => { + expect(execFileMock).not.toHaveBeenCalledWith( + "some-helm-binary-path", + ["repo", "update"], + ); + }); + }); + + describe("when configuration resolves without path to repository cache directory", () => { + beforeEach(async () => { + execFileMock.mockClear(); + + await execFileMock.resolveSpecific( + ["some-helm-binary-path", ["env"]], + "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("logs error", () => { + expect(loggerStub.warn).toHaveBeenCalledWith( + "Tried to get Helm repositories, but HELM_REPOSITORY_CACHE was not present in `$ helm env`. Behaving as if there were no repositories.", + ); + }); + + it("shows message about no repositories found", () => { + expect( + rendered.getByTestId("no-helm-repositories"), + ).toBeInTheDocument(); + }); + + it("does not show loader for repositories anymore", () => { + expect( + rendered.queryByTestId("helm-repositories-are-loading"), + ).not.toBeInTheDocument(); + }); + + it("does not call for updating of repositories", () => { + expect(execFileMock).not.toHaveBeenCalledWith( + "some-helm-binary-path", + ["repo", "update"], + ); + }); + }); + + describe("when configuration resolves", () => { + beforeEach(async () => { + execFileMock.mockClear(); + + await execFileMock.resolveSpecific( + ["some-helm-binary-path", ["env"]], + + [ + "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + ].join("\n"), + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("calls for update of repositories", () => { + expect(execFileMock).toHaveBeenCalledWith( + "some-helm-binary-path", + ["repo", "update"], + ); + }); + + it("does not call for repositories yet", () => { + expect(readYamlFileMock).not.toHaveBeenCalled(); + }); + + describe("when updating repositories resolve", () => { + beforeEach(async () => { + execFileMock.mockClear(); + + await execFileMock.resolveSpecific( + ["some-helm-binary-path", ["repo", "update"]], + "", + ); + }); + + describe("when loading repositories resolves with existing repositories", () => { + beforeEach(async () => { + execFileMock.mockClear(); + + await readYamlFileMock.resolveSpecific( + ["some-helm-repository-config-file.yaml"], + repositoryConfigStub, + ); + }); + + it("does not add default repository", () => { + expect(execFileMock).not.toHaveBeenCalledWith( + "some-helm-binary-path", + ["repo", "add", "bitnami", "https://charts.bitnami.com/bitnami"], + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("does not show loader for repositories anymore", () => { + expect( + rendered.queryByTestId("helm-repositories-are-loading"), + ).not.toBeInTheDocument(); + }); + + it("shows repositories in use", () => { + const actual = rendered.getAllByTestId( + /^helm-repository-(some-repository|some-other-repository)$/, + ); + + expect(actual).toHaveLength(2); + }); + }); + + describe("when loading repositories resolves with no existing repositories", () => { + beforeEach(async () => { + execFileMock.mockClear(); + + await readYamlFileMock.resolveSpecific( + ["some-helm-repository-config-file.yaml"], + { repositories: [] }, + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("still shows the loader for repositories", () => { + expect( + rendered.queryByTestId("helm-repositories-are-loading"), + ).toBeInTheDocument(); + }); + + it("does not show message about no repositories", () => { + expect( + rendered.queryByTestId("no-helm-repositories"), + ).not.toBeInTheDocument(); + }); + + it('adds "bitnami" as default repository', () => { + expect(execFileMock).toHaveBeenCalledWith( + "some-helm-binary-path", + ["repo", "add", "bitnami", "https://charts.bitnami.com/bitnami"], + ); + }); + + describe("when adding of default repository resolves", () => { + beforeEach(async () => { + readYamlFileMock.mockClear(); + + await execFileMock.resolveSpecific( + [ + "some-helm-binary-path", + + [ + "repo", + "add", + "bitnami", + "https://charts.bitnami.com/bitnami", + ], + ], + + "", + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("still shows the loader for repositories", () => { + expect( + rendered.queryByTestId("helm-repositories-are-loading"), + ).toBeInTheDocument(); + }); + + it("does not show message about no repositories", () => { + expect( + rendered.queryByTestId("no-helm-repositories"), + ).not.toBeInTheDocument(); + }); + + + it("calls for repositories again", () => { + expect(readYamlFileMock).toHaveBeenCalledWith( + "some-helm-repository-config-file.yaml", + ); + }); + + describe("when another call for repositories resolve", () => { + beforeEach(async () => { + await readYamlFileMock.resolveSpecific( + ["some-helm-repository-config-file.yaml"], + + { + repositories: [ + { + name: "bitnami", + url: "https://charts.bitnami.com/bitnami", + caFile: "irrelevant", + certFile: "irrelevant", + insecure_skip_tls_verify: false, + keyFile: "irrelevant", + pass_credentials_all: false, + password: "irrelevant", + username: "irrelevant", + }, + ], + }, + ); + }); + + it("does not show loader for repositories anymore", () => { + expect( + rendered.queryByTestId("helm-repositories-are-loading"), + ).not.toBeInTheDocument(); + }); + + it("shows the added repository", () => { + const actual = rendered.getByTestId("helm-repository-bitnami"); + + expect(actual).toBeInTheDocument(); + }); + + it("does not show message about no repositories", () => { + expect( + rendered.queryByTestId("no-helm-repositories"), + ).not.toBeInTheDocument(); + }); + }); + }); + }); + }); + }); + }); +}); + +const repositoryConfigStub: HelmRepositoriesFromYaml = { + repositories: [ + { + name: "some-repository", + url: "some-repository-url", + caFile: "irrelevant", + certFile: "irrelevant", + insecure_skip_tls_verify: false, + keyFile: "irrelevant", + pass_credentials_all: false, + password: "irrelevant", + username: "irrelevant", + }, + + { + name: "some-other-repository", + url: "some-other-repository-url", + caFile: "irrelevant", + certFile: "irrelevant", + insecure_skip_tls_verify: false, + keyFile: "irrelevant", + pass_credentials_all: false, + password: "irrelevant", + username: "irrelevant", + }, + ], +}; diff --git a/src/common/helm/get-active-helm-repositories-channel.injectable.ts b/src/common/helm/get-active-helm-repositories-channel.injectable.ts new file mode 100644 index 0000000000..7e913f64fb --- /dev/null +++ b/src/common/helm/get-active-helm-repositories-channel.injectable.ts @@ -0,0 +1,22 @@ +/** + * 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 { RequestChannel } from "../utils/channel/request-channel-injection-token"; +import type { HelmRepo } from "../helm-repo"; +import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; + +export type GetHelmRepositoriesChannel = RequestChannel; + +const getActiveHelmRepositoriesChannelInjectable = getInjectable({ + id: "get-active-helm-repositories-channel", + + instantiate: (): GetHelmRepositoriesChannel => ({ + id: "get-helm-active-list-repositories", + }), + + injectionToken: requestChannelInjectionToken, +}); + +export default getActiveHelmRepositoriesChannelInjectable; diff --git a/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts new file mode 100644 index 0000000000..e48ec7665e --- /dev/null +++ b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import getActiveHelmRepositoriesChannelInjectable from "../../../../common/helm/get-active-helm-repositories-channel.injectable"; +import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable"; + +const getActiveHelmRepositoriesChannelListenerInjectable = getInjectable({ + id: "get-active-helm-repositories-channel-listener", + + instantiate: (di) => { + const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable); + + return { + channel: di.inject(getActiveHelmRepositoriesChannelInjectable), + + handler: getActiveHelmRepositories, + }; + }, + + injectionToken: requestChannelListenerInjectionToken, +}); + +export default getActiveHelmRepositoriesChannelListenerInjectable; diff --git a/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts new file mode 100644 index 0000000000..107fabfab9 --- /dev/null +++ b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts @@ -0,0 +1,101 @@ +/** + * 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 { HelmRepo } from "../../../../common/helm-repo"; +import type { ReadYamlFile } from "../../../../common/fs/read-yaml-file.injectable"; +import readYamlFileInjectable from "../../../../common/fs/read-yaml-file.injectable"; +import getHelmEnvInjectable from "../../get-helm-env/get-helm-env.injectable"; +import execHelmInjectable from "../../exec-helm/exec-helm.injectable"; +import { isEmpty } from "lodash/fp"; +import loggerInjectable from "../../../../common/logger.injectable"; + +interface HelmRepositoryFromYaml { + name: string; + url: string; + caFile: string; + certFile: string; + insecure_skip_tls_verify: boolean; + keyFile: string; + pass_credentials_all: boolean; + password: string; + username: string; +} + +export interface HelmRepositoriesFromYaml { + repositories: HelmRepositoryFromYaml[]; +} + +const getActiveHelmRepositoriesInjectable = getInjectable({ + id: "get-helm-repositories", + + instantiate: (di) => { + const readYamlFile = di.inject(readYamlFileInjectable); + const execHelm = di.inject(execHelmInjectable); + const getHelmEnv = di.inject(getHelmEnvInjectable); + const logger = di.inject(loggerInjectable); + + const getRepositoriesFor = getRepositoriesForFor(readYamlFile); + + return async (): Promise => { + const { HELM_REPOSITORY_CONFIG: repositoryConfigFilePath, HELM_REPOSITORY_CACHE: helmRepositoryCacheDirPath } = await getHelmEnv(); + + if (!repositoryConfigFilePath) { + logger.warn("Tried to get Helm repositories, but HELM_REPOSITORY_CONFIG was not present in `$ helm env`. Behaving as if there were no repositories."); + + return []; + } + + if (!helmRepositoryCacheDirPath) { + logger.warn("Tried to get Helm repositories, but HELM_REPOSITORY_CACHE was not present in `$ helm env`. Behaving as if there were no repositories."); + + return []; + } + + if (!repositoryConfigFilePath || !helmRepositoryCacheDirPath) { + return []; + } + + const getRepositories = getRepositoriesFor( + repositoryConfigFilePath, + helmRepositoryCacheDirPath, + ); + + await execHelm("repo", "update"); + + const repositories = await getRepositories(); + + if (isEmpty(repositories)) { + await execHelm("repo", "add", "bitnami", "https://charts.bitnami.com/bitnami"); + + return await getRepositories(); + } + + return repositories; + }; + }, +}); + +export default getActiveHelmRepositoriesInjectable; + +const getRepositoriesForFor = + (readYamlFile: ReadYamlFile) => + (repositoryConfigFilePath: string, helmRepositoryCacheDirPath: string) => + async () => { + const { repositories } = (await readYamlFile( + repositoryConfigFilePath, + )) as HelmRepositoriesFromYaml; + + return repositories.map((repository) => ({ + name: repository.name, + url: repository.url, + caFile: repository.caFile, + certFile: repository.certFile, + insecureSkipTlsVerify: repository.insecure_skip_tls_verify, + keyFile: repository.keyFile, + username: repository.username, + password: repository.password, + cacheFilePath: `${helmRepositoryCacheDirPath}/${repository.name}-index.yaml`, + })); + }; diff --git a/src/renderer/components/+preferences/kubernetes.tsx b/src/renderer/components/+preferences/kubernetes.tsx index aaaffab0aa..51f013f406 100644 --- a/src/renderer/components/+preferences/kubernetes.tsx +++ b/src/renderer/components/+preferences/kubernetes.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import React from "react"; import { HelmCharts } from "./helm-charts"; +import { HelmCharts as HelmCharts2 } from "./kubernetes/helm-charts/helm-charts-2"; import { KubeconfigSyncs } from "./kubeconfig-syncs"; import { KubectlBinaries } from "./kubectl-binaries"; import { Preferences } from "./preferences"; @@ -26,6 +27,7 @@ export const Kubernetes = observer(() => (

Helm Charts

+
diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts new file mode 100644 index 0000000000..ed8b5e38e0 --- /dev/null +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts @@ -0,0 +1,24 @@ +/** + * 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 { asyncComputed } from "@ogre-tools/injectable-react"; +import requestFromChannelInjectable from "../../../../utils/channel/request-from-channel.injectable"; +import getActiveHelmRepositoriesChannelInjectable from "../../../../../common/helm/get-active-helm-repositories-channel.injectable"; + +const activeHelmRepositoriesInjectable = getInjectable({ + id: "active-helm-repositories", + + instantiate: (di) => { + const requestFromChannel = di.inject(requestFromChannelInjectable); + const getHelmRepositoriesChannel = di.inject(getActiveHelmRepositoriesChannelInjectable); + + return asyncComputed( + async () => await requestFromChannel(getHelmRepositoriesChannel), + [], + ); + }, +}); + +export default activeHelmRepositoriesInjectable; diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/helm-charts-2.tsx b/src/renderer/components/+preferences/kubernetes/helm-charts/helm-charts-2.tsx new file mode 100644 index 0000000000..879c135991 --- /dev/null +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/helm-charts-2.tsx @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + + +import React from "react"; + +import { HelmRepositories } from "./helm-repositories"; + +export const HelmCharts = () => ( +
+
+ +
+
+); + diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/helm-repositories.tsx b/src/renderer/components/+preferences/kubernetes/helm-charts/helm-repositories.tsx new file mode 100644 index 0000000000..bcb6bfcbd2 --- /dev/null +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/helm-repositories.tsx @@ -0,0 +1,65 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import styles from "../../helm-charts.module.scss"; + +import React from "react"; + +import { observer } from "mobx-react"; +import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable"; +import type { IAsyncComputed } from "@ogre-tools/injectable-react"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import { Spinner } from "../../../spinner"; +import type { HelmRepo } from "../../../../../common/helm-repo"; +import { Notice } from "../../../+extensions/notice"; +import { isEmpty } from "lodash/fp"; + +interface Dependencies { + activeHelmRepositories: IAsyncComputed; +} + +const NonInjectedActiveHelmRepositories = observer(({ activeHelmRepositories }: Dependencies) => { + if (activeHelmRepositories.pending.get()) { + return ; + } + + const repositories = activeHelmRepositories.value.get(); + + if (isEmpty(repositories)) { + return ( + +
+ The repositories have not been added yet +
+
+ ); + } + + return ( +
+ {repositories.map((repository) => ( +
+
+ {repository.name} +
+ +
{repository.url}
+
+ ))} +
+ ); + +}); + +export const HelmRepositories = withInjectables( + NonInjectedActiveHelmRepositories, + + { + getProps: (di) => ({ + activeHelmRepositories: di.inject(activeHelmRepositoriesInjectable), + }), + }, +); +