mirror of
https://github.com/lensapp/lens.git
synced 2024-09-19 05:17:22 +03:00
fix: Do not crash when opening details of a helm release
- Switch to using RequestChannel instead of LensProxy for better type safety Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
b7ac14df73
commit
40af0d31c5
@ -4,14 +4,14 @@
|
||||
*/
|
||||
|
||||
import type { ItemObject } from "@k8slens/list-layout";
|
||||
import type { HelmReleaseDetails } from "./helm-releases.api/request-details.injectable";
|
||||
import type { HelmReleaseData } from "../../../features/helm-releases/common/channels";
|
||||
|
||||
export interface HelmReleaseUpdateDetails {
|
||||
log: string;
|
||||
release: HelmReleaseDetails;
|
||||
release: HelmReleaseData;
|
||||
}
|
||||
|
||||
export interface HelmReleaseDto {
|
||||
export interface HelmRelease extends ItemObject {
|
||||
appVersion: string;
|
||||
name: string;
|
||||
namespace: string;
|
||||
@ -19,14 +19,10 @@ export interface HelmReleaseDto {
|
||||
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<string>;
|
||||
}
|
||||
|
@ -1,41 +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 { KubeJsonApiData } from "@k8slens/kube-object";
|
||||
import { urlBuilderFor } from "@k8slens/utilities";
|
||||
import apiBaseInjectable from "../../api-base.injectable";
|
||||
|
||||
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 type CallForHelmReleaseDetails = (name: string, namespace: string) => Promise<HelmReleaseDetails>;
|
||||
|
||||
const requestDetailsEndpoint = urlBuilderFor("/v2/releases/:namespace/:name");
|
||||
|
||||
const requestHelmReleaseDetailsInjectable = getInjectable({
|
||||
id: "call-for-helm-release-details",
|
||||
|
||||
instantiate: (di): CallForHelmReleaseDetails => {
|
||||
const apiBase = di.inject(apiBaseInjectable);
|
||||
|
||||
return (name, namespace) => apiBase.get(requestDetailsEndpoint.compile({ name, namespace }));
|
||||
},
|
||||
});
|
||||
|
||||
export default requestHelmReleaseDetailsInjectable;
|
@ -1,24 +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 { urlBuilderFor } from "@k8slens/utilities";
|
||||
import apiBaseInjectable from "../../api-base.injectable";
|
||||
import type { HelmReleaseDto } from "../helm-releases.api";
|
||||
|
||||
export type RequestHelmReleases = (namespace?: string) => Promise<HelmReleaseDto[]>;
|
||||
|
||||
const requestHelmReleasesEndpoint = urlBuilderFor("/v2/releases/:namespace?");
|
||||
|
||||
const requestHelmReleasesInjectable = getInjectable({
|
||||
id: "request-helm-releases",
|
||||
|
||||
instantiate: (di): RequestHelmReleases => {
|
||||
const apiBase = di.inject(apiBaseInjectable);
|
||||
|
||||
return (namespace) => apiBase.get(requestHelmReleasesEndpoint.compile({ namespace }));
|
||||
},
|
||||
});
|
||||
|
||||
export default requestHelmReleasesInjectable;
|
@ -28,9 +28,9 @@ import requestHelmChartReadmeInjectable from "../../../common/k8s-api/endpoints/
|
||||
import requestHelmChartValuesInjectable from "../../../common/k8s-api/endpoints/helm-charts.api/request-values.injectable";
|
||||
import type { RequestDetailedHelmRelease } from "../../../renderer/components/helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable";
|
||||
import requestDetailedHelmReleaseInjectable from "../../../renderer/components/helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable";
|
||||
import type { RequestHelmReleases } from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import requestHelmReleasesInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import { flushPromises } from "@k8slens/test-utils";
|
||||
import type { ListClusterHelmReleases } from "../../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
import listClusterHelmReleasesInjectable from "../../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
|
||||
describe("installing helm chart from new tab", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -40,7 +40,7 @@ describe("installing helm chart from new tab", () => {
|
||||
let requestHelmChartReadmeMock: AsyncFnMock<RequestHelmChartReadme>;
|
||||
let requestHelmChartValuesMock: AsyncFnMock<RequestHelmChartValues>;
|
||||
let requestCreateHelmReleaseMock: AsyncFnMock<RequestCreateHelmRelease>;
|
||||
let requestHelmReleasesMock: AsyncFnMock<RequestHelmReleases>;
|
||||
let listClusterHelmReleasesMock: AsyncFnMock<ListClusterHelmReleases>;
|
||||
|
||||
beforeEach(() => {
|
||||
builder = getApplicationBuilder();
|
||||
@ -53,7 +53,6 @@ describe("installing helm chart from new tab", () => {
|
||||
requestHelmChartReadmeMock = asyncFn();
|
||||
requestHelmChartValuesMock = asyncFn();
|
||||
requestCreateHelmReleaseMock = asyncFn();
|
||||
requestHelmReleasesMock = asyncFn();
|
||||
|
||||
builder.beforeWindowStart(({ windowDi }) => {
|
||||
windowDi.override(directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage");
|
||||
@ -63,7 +62,6 @@ describe("installing helm chart from new tab", () => {
|
||||
windowDi.override(requestHelmChartReadmeInjectable, () => requestHelmChartReadmeMock);
|
||||
windowDi.override(requestHelmChartValuesInjectable, () => requestHelmChartValuesMock);
|
||||
windowDi.override(requestCreateHelmReleaseInjectable, () => requestCreateHelmReleaseMock);
|
||||
windowDi.override(requestHelmReleasesInjectable, () => requestHelmReleasesMock);
|
||||
|
||||
windowDi.override(getRandomInstallChartTabIdInjectable, () =>
|
||||
jest
|
||||
@ -73,6 +71,11 @@ describe("installing helm chart from new tab", () => {
|
||||
);
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
listClusterHelmReleasesMock = asyncFn();
|
||||
mainDi.override(listClusterHelmReleasesInjectable, () => listClusterHelmReleasesMock);
|
||||
});
|
||||
|
||||
builder.namespaces.add("default");
|
||||
builder.namespaces.add("some-other-namespace");
|
||||
});
|
||||
@ -360,11 +363,10 @@ describe("installing helm chart from new tab", () => {
|
||||
log: "some-execution-output",
|
||||
|
||||
release: {
|
||||
resources: [],
|
||||
name: "some-release",
|
||||
namespace: "default",
|
||||
version: "some-version",
|
||||
config: "some-config",
|
||||
version: 1,
|
||||
config: {},
|
||||
manifest: "some-manifest",
|
||||
|
||||
info: {
|
||||
@ -400,7 +402,10 @@ describe("installing helm chart from new tab", () => {
|
||||
fireEvent.click(releaseButton);
|
||||
|
||||
await flushPromises();
|
||||
await requestHelmReleasesMock.resolve([]);
|
||||
await listClusterHelmReleasesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
@ -6,6 +6,7 @@
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { anyObject } from "jest-mock-extended";
|
||||
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 { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api";
|
||||
@ -15,8 +16,8 @@ import type { RequestHelmChartVersions } from "../../../common/k8s-api/endpoints
|
||||
import requestHelmChartVersionsInjectable from "../../../common/k8s-api/endpoints/helm-charts.api/request-versions.injectable";
|
||||
import type { RequestHelmReleaseConfiguration } from "../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
|
||||
import requestHelmReleaseConfigurationInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
|
||||
import type { RequestHelmReleases } from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import requestHelmReleasesInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import type { ListClusterHelmReleases } from "../../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
import listClusterHelmReleasesInjectable from "../../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
@ -26,9 +27,9 @@ describe("New Upgrade Helm Chart Dock Tab", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let renderResult: RenderResult;
|
||||
let requestHelmReleaseConfigurationMock: AsyncFnMock<RequestHelmReleaseConfiguration>;
|
||||
let requestHelmReleasesMock: AsyncFnMock<RequestHelmReleases>;
|
||||
let requestHelmChartsMock: AsyncFnMock<RequestHelmCharts>;
|
||||
let requestHelmChartVersionsMock: AsyncFnMock<RequestHelmChartVersions>;
|
||||
let listClusterHelmReleasesMock: AsyncFnMock<ListClusterHelmReleases>;
|
||||
let navigateToHelmReleases: NavigateToHelmReleases;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -39,9 +40,6 @@ describe("New Upgrade Helm Chart Dock Tab", () => {
|
||||
requestHelmReleaseConfigurationMock = asyncFn();
|
||||
windowDi.override(requestHelmReleaseConfigurationInjectable, () => requestHelmReleaseConfigurationMock);
|
||||
|
||||
requestHelmReleasesMock = asyncFn();
|
||||
windowDi.override(requestHelmReleasesInjectable, () => requestHelmReleasesMock);
|
||||
|
||||
requestHelmChartsMock = asyncFn();
|
||||
windowDi.override(requestHelmChartsInjectable, () => requestHelmChartsMock);
|
||||
|
||||
@ -51,6 +49,11 @@ describe("New Upgrade Helm Chart Dock Tab", () => {
|
||||
navigateToHelmReleases = windowDi.inject(navigateToHelmReleasesInjectable);
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
listClusterHelmReleasesMock = asyncFn();
|
||||
mainDi.override(listClusterHelmReleasesInjectable, () => listClusterHelmReleasesMock);
|
||||
});
|
||||
|
||||
testUsingFakeTime("2020-01-12 12:00:00");
|
||||
|
||||
builder.namespaces.add("my-first-namespace");
|
||||
@ -79,22 +82,25 @@ describe("New Upgrade Helm Chart Dock Tab", () => {
|
||||
});
|
||||
|
||||
it("requests helm releases for the selected namespace", () => {
|
||||
expect(requestHelmReleasesMock).toBeCalledWith("my-second-namespace");
|
||||
expect(listClusterHelmReleasesMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }), "my-second-namespace");
|
||||
});
|
||||
|
||||
describe("when helm releases resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await requestHelmReleasesMock.resolve([
|
||||
{
|
||||
appVersion: "some-app-version",
|
||||
name: "some-name",
|
||||
namespace: "my-second-namespace",
|
||||
chart: "some-chart-1.0.0",
|
||||
status: "some-status",
|
||||
updated: "some-updated",
|
||||
revision: "some-revision",
|
||||
},
|
||||
]);
|
||||
await listClusterHelmReleasesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{
|
||||
app_version: "some-app-version",
|
||||
name: "some-name",
|
||||
namespace: "my-second-namespace",
|
||||
chart: "some-chart-1.0.0",
|
||||
status: "some-status",
|
||||
updated: "some-updated",
|
||||
revision: "some-revision",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
59
packages/core/src/features/helm-releases/common/channels.ts
Normal file
59
packages/core/src/features/helm-releases/common/channels.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getRequestChannel } from "@k8slens/messaging";
|
||||
import type { Result } from "@k8slens/utilities";
|
||||
import type { KubeJsonApiData } from "@k8slens/kube-object";
|
||||
|
||||
export interface GetHelmReleaseArgs {
|
||||
clusterId: string;
|
||||
releaseName: string;
|
||||
namespace: string;
|
||||
}
|
||||
|
||||
export interface HelmReleaseInfo {
|
||||
first_deployed: string;
|
||||
last_deployed: string;
|
||||
deleted: string;
|
||||
description: string;
|
||||
status: string;
|
||||
notes: string;
|
||||
}
|
||||
|
||||
export interface HelmReleaseDataWithResources extends HelmReleaseData {
|
||||
resources: KubeJsonApiData[];
|
||||
}
|
||||
|
||||
export interface HelmReleaseData {
|
||||
name: string;
|
||||
info: HelmReleaseInfo;
|
||||
config: Record<string, unknown>;
|
||||
manifest: string;
|
||||
version: number;
|
||||
namespace: string;
|
||||
}
|
||||
|
||||
export type GetHelmReleaseResponse = Result<HelmReleaseDataWithResources, string>;
|
||||
|
||||
export const getHelmReleaseChannel = getRequestChannel<GetHelmReleaseArgs, GetHelmReleaseResponse>("get-helm-release");
|
||||
|
||||
export interface ListedHelmRelease {
|
||||
name: string;
|
||||
namespace: string;
|
||||
revision: string;
|
||||
updated: string;
|
||||
status: string;
|
||||
chart: string;
|
||||
app_version: string;
|
||||
}
|
||||
|
||||
export interface ListHelmReleasesArgs {
|
||||
namespace?: string;
|
||||
clusterId: string;
|
||||
}
|
||||
|
||||
export type ListHelmReleasesResponse = Result<ListedHelmRelease[], string>;
|
||||
|
||||
export const listHelmReleasesChannel = getRequestChannel<ListHelmReleasesArgs, ListHelmReleasesResponse>("list-helm-releases");
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
|
||||
import getHelmReleaseInjectable from "../../../main/helm/helm-service/get-helm-release.injectable";
|
||||
import getClusterByIdInjectable from "../../cluster/storage/common/get-by-id.injectable";
|
||||
import { getHelmReleaseChannel } from "../common/channels";
|
||||
|
||||
const handleGetHelmReleaseInjectable = getRequestChannelListenerInjectable({
|
||||
channel: getHelmReleaseChannel,
|
||||
getHandler: (di) => {
|
||||
const getHelmRelease = di.inject(getHelmReleaseInjectable);
|
||||
const getClusterById = di.inject(getClusterByIdInjectable);
|
||||
|
||||
return async ({ clusterId, ...args }) => {
|
||||
const cluster = getClusterById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Cluster with id "${clusterId}" not found`,
|
||||
};
|
||||
}
|
||||
|
||||
return getHelmRelease({
|
||||
cluster,
|
||||
...args,
|
||||
});
|
||||
};
|
||||
},
|
||||
id: "handle-get-helm-release",
|
||||
});
|
||||
|
||||
export default handleGetHelmReleaseInjectable;
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
|
||||
import listClusterHelmReleasesInjectable from "../../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
import getClusterByIdInjectable from "../../cluster/storage/common/get-by-id.injectable";
|
||||
import { listHelmReleasesChannel } from "../common/channels";
|
||||
|
||||
const handleListHelmReleasesInjectable = getRequestChannelListenerInjectable({
|
||||
channel: listHelmReleasesChannel,
|
||||
id: "handle-list-helm-releases",
|
||||
getHandler: (di) => {
|
||||
const listClusterHelmReleases = di.inject(listClusterHelmReleasesInjectable);
|
||||
const getClusterById = di.inject(getClusterByIdInjectable);
|
||||
|
||||
return async ({ clusterId, namespace }) => {
|
||||
const cluster = getClusterById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Cluster with id "${clusterId}" not found`,
|
||||
};
|
||||
}
|
||||
|
||||
return listClusterHelmReleases(cluster, namespace);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default handleListHelmReleasesInjectable;
|
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ChannelRequester } from "@k8slens/messaging";
|
||||
import { requestFromChannelInjectionToken } from "@k8slens/messaging";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { listHelmReleasesChannel } from "../common/channels";
|
||||
|
||||
export type RequestListHelmReleases = ChannelRequester<typeof listHelmReleasesChannel>;
|
||||
|
||||
const requestListHelmReleasesInjectable = getInjectable({
|
||||
id: "request-list-helm-releases",
|
||||
instantiate: (di): RequestListHelmReleases => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
|
||||
return (args) => requestFromChannel(listHelmReleasesChannel, args);
|
||||
},
|
||||
});
|
||||
|
||||
export default requestListHelmReleasesInjectable;
|
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { ChannelRequester } from "@k8slens/messaging";
|
||||
import { requestFromChannelInjectionToken } from "@k8slens/messaging";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { getHelmReleaseChannel } from "../common/channels";
|
||||
|
||||
export type RequestHelmRelease = ChannelRequester<typeof getHelmReleaseChannel>;
|
||||
|
||||
const requestHelmReleaseInjectable = getInjectable({
|
||||
id: "request-helm-release",
|
||||
instantiate: (di): RequestHelmRelease => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
|
||||
return (args) => requestFromChannel(getHelmReleaseChannel, args);
|
||||
},
|
||||
});
|
||||
|
||||
export default requestHelmReleaseInjectable;
|
@ -9,8 +9,6 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import { fireEvent } from "@testing-library/react";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { RequestHelmReleases } from "../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import requestHelmReleasesInjectable from "../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import type { RequestHelmReleaseConfiguration } from "../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
|
||||
import requestHelmReleaseConfigurationInjectable from "../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
|
||||
import type { RequestHelmReleaseUpdate } from "../../common/k8s-api/endpoints/helm-releases.api/request-update.injectable";
|
||||
@ -30,10 +28,13 @@ import requestHelmChartReadmeInjectable from "../../common/k8s-api/endpoints/hel
|
||||
import requestHelmChartValuesInjectable from "../../common/k8s-api/endpoints/helm-charts.api/request-values.injectable";
|
||||
import { HelmChart } from "../../common/k8s-api/endpoints/helm-charts.api";
|
||||
import { testUsingFakeTime } from "../../test-utils/use-fake-time";
|
||||
import type { ListClusterHelmReleases } from "../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
import listClusterHelmReleasesInjectable from "../../main/helm/helm-service/list-helm-releases.injectable";
|
||||
import { anyObject } from "jest-mock-extended";
|
||||
import { toHelmRelease } from "../../renderer/components/helm-releases/to-helm-release";
|
||||
|
||||
describe("showing details for helm release", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let requestHelmReleasesMock: AsyncFnMock<RequestHelmReleases>;
|
||||
let requestDetailedHelmReleaseMock: AsyncFnMock<RequestDetailedHelmRelease>;
|
||||
let requestHelmReleaseConfigurationMock: AsyncFnMock<RequestHelmReleaseConfiguration>;
|
||||
let requestHelmReleaseUpdateMock: AsyncFnMock<RequestHelmReleaseUpdate>;
|
||||
@ -43,6 +44,7 @@ describe("showing details for helm release", () => {
|
||||
let requestHelmChartValuesMock: AsyncFnMock<RequestHelmChartValues>;
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showCheckedErrorNotificationMock: jest.Mock;
|
||||
let listClusterHelmReleasesMock: AsyncFnMock<ListClusterHelmReleases>;
|
||||
|
||||
beforeEach(() => {
|
||||
testUsingFakeTime("2015-10-21T07:28:00Z");
|
||||
@ -51,7 +53,6 @@ describe("showing details for helm release", () => {
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
requestHelmReleasesMock = asyncFn();
|
||||
requestDetailedHelmReleaseMock = asyncFn();
|
||||
requestHelmReleaseConfigurationMock = asyncFn();
|
||||
requestHelmReleaseUpdateMock = asyncFn();
|
||||
@ -67,7 +68,6 @@ describe("showing details for helm release", () => {
|
||||
windowDi.override(getRandomUpgradeChartTabIdInjectable, () => () => "some-tab-id");
|
||||
windowDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
windowDi.override(showCheckedErrorInjectable, () => showCheckedErrorNotificationMock);
|
||||
windowDi.override(requestHelmReleasesInjectable, () => requestHelmReleasesMock);
|
||||
windowDi.override(requestDetailedHelmReleaseInjectable, () => requestDetailedHelmReleaseMock);
|
||||
windowDi.override(requestHelmReleaseConfigurationInjectable, () => requestHelmReleaseConfigurationMock);
|
||||
windowDi.override(requestHelmReleaseUpdateInjectable, () => requestHelmReleaseUpdateMock);
|
||||
@ -77,6 +77,11 @@ describe("showing details for helm release", () => {
|
||||
windowDi.override(requestHelmChartValuesInjectable, () => requestHelmChartValuesMock);
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
listClusterHelmReleasesMock = asyncFn();
|
||||
mainDi.override(listClusterHelmReleasesInjectable, () => listClusterHelmReleasesMock);
|
||||
});
|
||||
|
||||
builder.namespaces.add("some-namespace");
|
||||
builder.namespaces.add("some-other-namespace");
|
||||
builder.namespaces.add("some-third-namespace");
|
||||
@ -110,9 +115,9 @@ describe("showing details for helm release", () => {
|
||||
});
|
||||
|
||||
it("calls for releases for each selected namespace", () => {
|
||||
expect(requestHelmReleasesMock).toBeCalledTimes(2);
|
||||
expect(requestHelmReleasesMock).toBeCalledWith("some-namespace");
|
||||
expect(requestHelmReleasesMock).toBeCalledWith("some-other-namespace");
|
||||
expect(listClusterHelmReleasesMock).toBeCalledTimes(2);
|
||||
expect(listClusterHelmReleasesMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }), "some-namespace");
|
||||
expect(listClusterHelmReleasesMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }), "some-other-namespace");
|
||||
});
|
||||
|
||||
it("shows spinner", () => {
|
||||
@ -122,42 +127,54 @@ describe("showing details for helm release", () => {
|
||||
});
|
||||
|
||||
it("when releases resolve but there is none, renders", async () => {
|
||||
await requestHelmReleasesMock.resolve([]);
|
||||
await requestHelmReleasesMock.resolve([]);
|
||||
await listClusterHelmReleasesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [],
|
||||
});
|
||||
await listClusterHelmReleasesMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [],
|
||||
});
|
||||
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when releases resolve", () => {
|
||||
beforeEach(async () => {
|
||||
await requestHelmReleasesMock.resolveSpecific(
|
||||
([namespace]) => namespace === "some-namespace",
|
||||
[
|
||||
{
|
||||
appVersion: "some-app-version",
|
||||
name: "some-name",
|
||||
namespace: "some-namespace",
|
||||
chart: "some-chart-1.0.0",
|
||||
status: "some-status",
|
||||
updated: "some-updated",
|
||||
revision: "some-revision",
|
||||
},
|
||||
],
|
||||
await listClusterHelmReleasesMock.resolveSpecific(
|
||||
([, namespace]) => namespace === "some-namespace",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{
|
||||
app_version: "some-app-version",
|
||||
name: "some-name",
|
||||
namespace: "some-namespace",
|
||||
chart: "some-chart-1.0.0",
|
||||
status: "some-status",
|
||||
updated: "some-updated",
|
||||
revision: "some-revision",
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
await requestHelmReleasesMock.resolveSpecific(
|
||||
([namespace]) => namespace === "some-other-namespace",
|
||||
[
|
||||
{
|
||||
appVersion: "some-other-app-version",
|
||||
name: "some-other-name",
|
||||
namespace: "some-other-namespace",
|
||||
chart: "some-other-chart-2.0.0",
|
||||
status: "some-other-status",
|
||||
updated: "some-other-updated",
|
||||
revision: "some-other-revision",
|
||||
},
|
||||
],
|
||||
await listClusterHelmReleasesMock.resolveSpecific(
|
||||
([, namespace]) => namespace === "some-other-namespace",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
{
|
||||
app_version: "some-other-app-version",
|
||||
name: "some-other-name",
|
||||
namespace: "some-other-namespace",
|
||||
chart: "some-other-chart-2.0.0",
|
||||
status: "some-other-status",
|
||||
updated: "some-other-updated",
|
||||
revision: "some-other-revision",
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -191,10 +208,11 @@ describe("showing details for helm release", () => {
|
||||
});
|
||||
|
||||
it("calls for release", () => {
|
||||
expect(requestDetailedHelmReleaseMock).toHaveBeenCalledWith(
|
||||
"some-name",
|
||||
"some-namespace",
|
||||
);
|
||||
expect(requestDetailedHelmReleaseMock).toHaveBeenCalledWith({
|
||||
clusterId: "some-cluster-id",
|
||||
namespace: "some-namespace",
|
||||
releaseName: "some-name",
|
||||
});
|
||||
});
|
||||
|
||||
it("shows spinner", () => {
|
||||
@ -219,10 +237,11 @@ describe("showing details for helm release", () => {
|
||||
});
|
||||
|
||||
it("calls for another release", () => {
|
||||
expect(requestDetailedHelmReleaseMock).toHaveBeenCalledWith(
|
||||
"some-other-name",
|
||||
"some-other-namespace",
|
||||
);
|
||||
expect(requestDetailedHelmReleaseMock).toHaveBeenCalledWith({
|
||||
clusterId: "some-cluster-id",
|
||||
namespace: "some-other-namespace",
|
||||
releaseName: "some-other-name",
|
||||
});
|
||||
});
|
||||
|
||||
it("closes details for first release", () => {
|
||||
@ -252,21 +271,21 @@ describe("showing details for helm release", () => {
|
||||
await requestDetailedHelmReleaseMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: {
|
||||
release: {
|
||||
appVersion: "some-app-version",
|
||||
release: toHelmRelease({
|
||||
app_version: "some-app-version",
|
||||
chart: "some-chart-1.0.0",
|
||||
status: "some-status",
|
||||
updated: "some-updated",
|
||||
revision: "some-revision",
|
||||
name: "some-other-name",
|
||||
namespace: "some-other-namespace",
|
||||
},
|
||||
}),
|
||||
|
||||
details: {
|
||||
name: "some-other-name",
|
||||
namespace: "some-other-namespace",
|
||||
version: "some-version",
|
||||
config: "some-config",
|
||||
version: 1,
|
||||
config: {},
|
||||
manifest: "some-manifest",
|
||||
|
||||
info: {
|
||||
@ -393,21 +412,21 @@ describe("showing details for helm release", () => {
|
||||
await requestDetailedHelmReleaseMock.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: {
|
||||
release: {
|
||||
appVersion: "some-app-version",
|
||||
release: toHelmRelease({
|
||||
app_version: "some-app-version",
|
||||
chart: "some-chart-1.0.0",
|
||||
status: "some-status",
|
||||
updated: "some-updated",
|
||||
revision: "some-revision",
|
||||
name: "some-name",
|
||||
namespace: "some-namespace",
|
||||
},
|
||||
}),
|
||||
|
||||
details: {
|
||||
name: "some-name",
|
||||
namespace: "some-namespace",
|
||||
version: "some-version",
|
||||
config: "some-config",
|
||||
version: 1,
|
||||
config: {},
|
||||
manifest: "some-manifest",
|
||||
|
||||
info: {
|
||||
@ -632,7 +651,7 @@ describe("showing details for helm release", () => {
|
||||
|
||||
describe("when update resolves with success", () => {
|
||||
beforeEach(async () => {
|
||||
requestHelmReleasesMock.mockClear();
|
||||
listClusterHelmReleasesMock.mockClear();
|
||||
requestHelmReleaseConfigurationMock.mockClear();
|
||||
|
||||
await requestHelmReleaseUpdateMock.resolve({
|
||||
@ -671,7 +690,7 @@ describe("showing details for helm release", () => {
|
||||
|
||||
describe("when update resolves with failure", () => {
|
||||
beforeEach(async () => {
|
||||
requestHelmReleasesMock.mockClear();
|
||||
listClusterHelmReleasesMock.mockClear();
|
||||
requestHelmReleaseConfigurationMock.mockClear();
|
||||
|
||||
await requestHelmReleaseUpdateMock.resolve({
|
||||
|
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import { isObject, json } from "@k8slens/utilities";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { HelmReleaseData } from "../../../features/helm-releases/common/channels";
|
||||
import execHelmInjectable from "../exec-helm/exec-helm.injectable";
|
||||
|
||||
export type GetHelmReleaseData = (
|
||||
name: string,
|
||||
namespace: string,
|
||||
kubeconfigPath: string,
|
||||
) => AsyncResult<HelmReleaseData, string>;
|
||||
|
||||
const getHelmReleaseDataInjectable = getInjectable({
|
||||
id: "get-helm-release-data",
|
||||
instantiate: (di): GetHelmReleaseData => {
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
|
||||
return async (releaseName, namespace, proxyKubeconfigPath) => {
|
||||
const result = await execHelm([
|
||||
"status",
|
||||
releaseName,
|
||||
"--namespace",
|
||||
namespace,
|
||||
"--kubeconfig",
|
||||
proxyKubeconfigPath,
|
||||
"--output",
|
||||
"json",
|
||||
]);
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Failed to execute helm: ${result.error}`,
|
||||
};
|
||||
}
|
||||
|
||||
const parseResult = json.parse(result.response);
|
||||
|
||||
if (!parseResult.callWasSuccessful) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Failed to parse helm response: ${parseResult.error}`,
|
||||
};
|
||||
}
|
||||
|
||||
const release = parseResult.response;
|
||||
|
||||
if (!isObject(release) || Array.isArray(release)) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Helm response is not an object: ${JSON.stringify(release)}`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: release as unknown as HelmReleaseData,
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default getHelmReleaseDataInjectable;
|
@ -4,12 +4,13 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import { isObject } from "@k8slens/utilities";
|
||||
import execHelmInjectable from "../../../exec-helm/exec-helm.injectable";
|
||||
import yaml from "js-yaml";
|
||||
import type { KubeJsonApiData, KubeJsonApiDataList } from "@k8slens/kube-object";
|
||||
|
||||
const callForHelmManifestInjectable = getInjectable({
|
||||
id: "call-for-helm-manifest",
|
||||
const requestHelmManifestInjectable = getInjectable({
|
||||
id: "request-helm-manifest",
|
||||
|
||||
instantiate: (di) => {
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
@ -37,11 +38,11 @@ const callForHelmManifestInjectable = getInjectable({
|
||||
callWasSuccessful: true,
|
||||
response: yaml
|
||||
.loadAll(result.response)
|
||||
.filter((manifest) => !!manifest) as KubeJsonApiData[],
|
||||
.filter(isObject) as unknown as KubeJsonApiData[],
|
||||
};
|
||||
};
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
export default callForHelmManifestInjectable;
|
||||
export default requestHelmManifestInjectable;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import callForHelmManifestInjectable from "./call-for-helm-manifest/call-for-helm-manifest.injectable";
|
||||
import requestHelmManifestInjectable from "./call-for-helm-manifest/call-for-helm-manifest.injectable";
|
||||
import type { KubeJsonApiData, KubeJsonApiDataList } from "@k8slens/kube-object";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
|
||||
@ -17,10 +17,10 @@ const getHelmReleaseResourcesInjectable = getInjectable({
|
||||
id: "get-helm-release-resources",
|
||||
|
||||
instantiate: (di): GetHelmReleaseResources => {
|
||||
const callForHelmManifest = di.inject(callForHelmManifestInjectable);
|
||||
const requestHelmManifest = di.inject(requestHelmManifestInjectable);
|
||||
|
||||
return async (name, namespace, kubeconfigPath) => {
|
||||
const result = await callForHelmManifest(name, namespace, kubeconfigPath);
|
||||
const result = await requestHelmManifest(name, namespace, kubeconfigPath);
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
return result;
|
||||
|
@ -4,47 +4,42 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable";
|
||||
import { isObject, json } from "@k8slens/utilities";
|
||||
import execHelmInjectable from "../exec-helm/exec-helm.injectable";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import getHelmReleaseResourcesInjectable from "./get-helm-release-resources/get-helm-release-resources.injectable";
|
||||
import type { HelmReleaseDataWithResources } from "../../../features/helm-releases/common/channels";
|
||||
import getHelmReleaseDataInjectable from "./get-helm-release-data.injectable";
|
||||
|
||||
export interface GetHelmReleaseArgs {
|
||||
cluster: Cluster;
|
||||
releaseName: string;
|
||||
namespace: string;
|
||||
}
|
||||
|
||||
export type GetHelmRelease = (args: GetHelmReleaseArgs) => AsyncResult<HelmReleaseDataWithResources, string>;
|
||||
|
||||
const getHelmReleaseInjectable = getInjectable({
|
||||
id: "get-helm-release",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectionToken);
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
instantiate: (di): GetHelmRelease => {
|
||||
const getHelmReleaseData = di.inject(getHelmReleaseDataInjectable);
|
||||
const getHelmReleaseResources = di.inject(getHelmReleaseResourcesInjectable);
|
||||
|
||||
return async (cluster: Cluster, releaseName: string, namespace: string) => {
|
||||
return async ({ cluster, namespace, releaseName }) => {
|
||||
const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster);
|
||||
const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath();
|
||||
|
||||
logger.debug("Fetch release");
|
||||
|
||||
const result = await execHelm([
|
||||
"status",
|
||||
const releaseResult = await getHelmReleaseData(
|
||||
releaseName,
|
||||
"--namespace",
|
||||
namespace,
|
||||
"--kubeconfig",
|
||||
proxyKubeconfigPath,
|
||||
"--output",
|
||||
"json",
|
||||
]);
|
||||
);
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
logger.warn(`Failed to exectute helm: ${result.error}`);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const release = json.parse(result.response);
|
||||
|
||||
if (!isObject(release) || Array.isArray(release)) {
|
||||
return undefined;
|
||||
if (!releaseResult.callWasSuccessful) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Failed to get helm release data: ${releaseResult.error}`,
|
||||
};
|
||||
}
|
||||
|
||||
const resourcesResult = await getHelmReleaseResources(
|
||||
@ -54,14 +49,18 @@ const getHelmReleaseInjectable = getInjectable({
|
||||
);
|
||||
|
||||
if (!resourcesResult.callWasSuccessful) {
|
||||
logger.warn(`Failed to get helm release resources: ${resourcesResult.error}`);
|
||||
|
||||
return undefined;
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Failed to get helm release resources: ${resourcesResult.error}`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...release,
|
||||
resources: resourcesResult.response,
|
||||
callWasSuccessful: true,
|
||||
response: {
|
||||
...releaseResult.response,
|
||||
resources: resourcesResult.response,
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
|
@ -7,15 +7,19 @@ import type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable";
|
||||
import listHelmReleasesInjectable from "../list-helm-releases.injectable";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import type { ListedHelmRelease } from "../../../features/helm-releases/common/channels";
|
||||
|
||||
export type ListClusterHelmReleases = (cluster: Cluster, namespace?: string) => AsyncResult<ListedHelmRelease[], string>;
|
||||
|
||||
const listClusterHelmReleasesInjectable = getInjectable({
|
||||
id: "list-cluster-helm-releases",
|
||||
|
||||
instantiate: (di) => {
|
||||
instantiate: (di): ListClusterHelmReleases => {
|
||||
const logger = di.inject(loggerInjectionToken);
|
||||
const listHelmReleases = di.inject(listHelmReleasesInjectable);
|
||||
|
||||
return async (cluster: Cluster, namespace?: string) => {
|
||||
return async (cluster, namespace) => {
|
||||
const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster);
|
||||
const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath();
|
||||
|
||||
|
@ -52,9 +52,15 @@ const updateHelmReleaseInjectable = getInjectable({
|
||||
throw result.error; // keep the same interface
|
||||
}
|
||||
|
||||
const releaseResult = await getHelmRelease({ cluster, releaseName, namespace });
|
||||
|
||||
if (!releaseResult.callWasSuccessful) {
|
||||
throw releaseResult.error; // keep the same interface
|
||||
}
|
||||
|
||||
return {
|
||||
log: result.response,
|
||||
release: await getHelmRelease(cluster, releaseName, namespace),
|
||||
release: releaseResult.response,
|
||||
};
|
||||
} finally {
|
||||
await removePath(valuesFilePath);
|
||||
|
@ -4,9 +4,11 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import execHelmInjectable from "./exec-helm/exec-helm.injectable";
|
||||
import { toCamelCase, isObject } from "@k8slens/utilities";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import { isObject } from "@k8slens/utilities";
|
||||
import type { ListedHelmRelease } from "../../features/helm-releases/common/channels";
|
||||
|
||||
export type ListHelmReleases = (pathToKubeconfig: string, namespace?: string) => Promise<Record<string, any>[]>;
|
||||
export type ListHelmReleases = (pathToKubeconfig: string, namespace?: string) => AsyncResult<ListedHelmRelease[], string>;
|
||||
|
||||
const listHelmReleasesInjectable = getInjectable({
|
||||
id: "list-helm-releases",
|
||||
@ -33,16 +35,21 @@ const listHelmReleasesInjectable = getInjectable({
|
||||
const result = await execHelm(args);
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
throw result.error;
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Failed to list helm releases: ${result.error}`,
|
||||
};
|
||||
}
|
||||
|
||||
const output = JSON.parse(result.response);
|
||||
const rawOutput = JSON.parse(result.response);
|
||||
const output = Array.isArray(rawOutput)
|
||||
? rawOutput.filter(isObject)
|
||||
: [];
|
||||
|
||||
if (!Array.isArray(output) || output.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return output.filter(isObject).map(toCamelCase);
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: output as unknown as ListedHelmRelease[],
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { apiPrefix } from "../../../../common/vars";
|
||||
import { getRouteInjectable } from "../../../router/router.injectable";
|
||||
import { clusterRoute } from "../../../router/route";
|
||||
import getHelmReleaseInjectable from "../../../helm/helm-service/get-helm-release.injectable";
|
||||
|
||||
const getReleaseRouteInjectable = getRouteInjectable({
|
||||
id: "get-release-route",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getHelmRelease = di.inject(getHelmReleaseInjectable);
|
||||
|
||||
return clusterRoute({
|
||||
method: "get",
|
||||
path: `${apiPrefix}/v2/releases/{namespace}/{release}`,
|
||||
})(async ({ cluster, params }) => ({
|
||||
response: await getHelmRelease(
|
||||
cluster,
|
||||
params.release,
|
||||
params.namespace,
|
||||
),
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export default getReleaseRouteInjectable;
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { apiPrefix } from "../../../../common/vars";
|
||||
import { getRouteInjectable } from "../../../router/router.injectable";
|
||||
import { clusterRoute } from "../../../router/route";
|
||||
import listClusterHelmReleasesInjectable from "../../../helm/helm-service/list-helm-releases.injectable";
|
||||
|
||||
const listReleasesRouteInjectable = getRouteInjectable({
|
||||
id: "list-releases-route",
|
||||
|
||||
instantiate: (di) => {
|
||||
const listHelmReleases = di.inject(listClusterHelmReleasesInjectable);
|
||||
|
||||
return clusterRoute({
|
||||
method: "get",
|
||||
path: `${apiPrefix}/v2/releases/{namespace?}`,
|
||||
})(async ({ cluster, params }) => ({
|
||||
response: await listHelmReleases(cluster, params.namespace),
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export default listReleasesRouteInjectable;
|
@ -26,7 +26,7 @@ const helmChartVersionsInjectable = getInjectable({
|
||||
},
|
||||
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, release: HelmRelease) => release.getName(),
|
||||
getInstanceKey: (di, release: HelmRelease) => `${release.namespace}/${release.name}}`,
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -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, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { when } from "mobx";
|
||||
import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import helmChartVersionsInjectable from "../helm-charts/helm-charts/versions.injectable";
|
||||
|
||||
const helmChartRepoInjectable = getInjectable({
|
||||
id: "helm-chart-repo",
|
||||
instantiate: (di, release) => {
|
||||
const chartVersions = di.inject(helmChartVersionsInjectable, release);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async () => {
|
||||
await when(() => !chartVersions.pending.get());
|
||||
|
||||
const version = release.getVersion();
|
||||
|
||||
return chartVersions.value
|
||||
.get()
|
||||
.find((chartVersion) => chartVersion.version === version)?.repo;
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, release: HelmRelease) => `${release.namespace}/${release.name}`,
|
||||
}),
|
||||
});
|
||||
|
||||
export default helmChartRepoInjectable;
|
@ -29,17 +29,24 @@ import type { NavigateToHelmReleases } from "../../../../../common/front-end-rou
|
||||
import navigateToHelmReleasesInjectable from "../../../../../common/front-end-routing/routes/cluster/helm/releases/navigate-to-helm-releases.injectable";
|
||||
import assert from "assert";
|
||||
import activeThemeInjectable from "../../../../themes/active.injectable";
|
||||
import type { ToHelmRelease } from "../../to-helm-release.injectable";
|
||||
import toHelmReleaseInjectable from "../../to-helm-release.injectable";
|
||||
import hostedClusterIdInjectable from "../../../../cluster-frame-context/hosted-cluster-id.injectable";
|
||||
import helmChartRepoInjectable from "../../helm-chart-repo.injectable";
|
||||
import type { IAsyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { waitUntilDefined } from "@k8slens/utilities";
|
||||
|
||||
const releaseDetailsModelInjectable = getInjectable({
|
||||
id: "release-details-model",
|
||||
|
||||
instantiate: async (di, targetRelease: TargetHelmRelease) => {
|
||||
const clusterId = di.inject(hostedClusterIdInjectable);
|
||||
|
||||
assert(clusterId, "Cluster id is required");
|
||||
|
||||
const model = new ReleaseDetailsModel({
|
||||
requestDetailedHelmRelease: di.inject(requestDetailedHelmReleaseInjectable),
|
||||
targetRelease,
|
||||
activeTheme: di.inject(activeThemeInjectable),
|
||||
clusterId,
|
||||
requestHelmReleaseConfiguration: di.inject(requestHelmReleaseConfigurationInjectable),
|
||||
getResourceDetailsUrl: di.inject(getResourceDetailsUrlInjectable),
|
||||
updateRelease: di.inject(updateReleaseInjectable),
|
||||
@ -47,7 +54,7 @@ const releaseDetailsModelInjectable = getInjectable({
|
||||
showSuccessNotification: di.inject(showSuccessNotificationInjectable),
|
||||
createUpgradeChartTab: di.inject(createUpgradeChartTabInjectable),
|
||||
navigateToHelmReleases: di.inject(navigateToHelmReleasesInjectable),
|
||||
toHelmRelease: di.inject(toHelmReleaseInjectable),
|
||||
helmChartRepo: di.injectFactory(helmChartRepoInjectable),
|
||||
});
|
||||
|
||||
await model.load();
|
||||
@ -78,6 +85,7 @@ export interface ConfigurationInput {
|
||||
interface Dependencies {
|
||||
readonly targetRelease: TargetHelmRelease;
|
||||
readonly activeTheme: IComputedValue<LensTheme>;
|
||||
readonly clusterId: string;
|
||||
requestDetailedHelmRelease: RequestDetailedHelmRelease;
|
||||
requestHelmReleaseConfiguration: RequestHelmReleaseConfiguration;
|
||||
getResourceDetailsUrl: GetResourceDetailsUrl;
|
||||
@ -86,7 +94,7 @@ interface Dependencies {
|
||||
showSuccessNotification: ShowNotification;
|
||||
createUpgradeChartTab: (release: HelmRelease) => string;
|
||||
navigateToHelmReleases: NavigateToHelmReleases;
|
||||
toHelmRelease: ToHelmRelease;
|
||||
helmChartRepo: (release: HelmRelease) => IAsyncComputed<string | undefined>;
|
||||
}
|
||||
|
||||
export class ReleaseDetailsModel {
|
||||
@ -114,10 +122,12 @@ export class ReleaseDetailsModel {
|
||||
|
||||
const name = this.release.getName();
|
||||
const namespace = this.release.getNs();
|
||||
const helmChartRepo = this.dependencies.helmChartRepo(this.release);
|
||||
const repo = await waitUntilDefined(helmChartRepo.value);
|
||||
|
||||
const data = {
|
||||
chart: this.release.getChart(),
|
||||
repo: await this.release.getRepo(),
|
||||
repo,
|
||||
version: this.release.getVersion(),
|
||||
values: this.configuration.nonSavedValue.get(),
|
||||
};
|
||||
@ -165,10 +175,11 @@ export class ReleaseDetailsModel {
|
||||
load = async () => {
|
||||
const { name, namespace } = this.dependencies.targetRelease;
|
||||
|
||||
const result = await this.dependencies.requestDetailedHelmRelease(
|
||||
name,
|
||||
const result = await this.dependencies.requestDetailedHelmRelease({
|
||||
releaseName: name,
|
||||
namespace,
|
||||
);
|
||||
clusterId: this.dependencies.clusterId,
|
||||
});
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
runInAction(() => {
|
||||
@ -210,7 +221,7 @@ export class ReleaseDetailsModel {
|
||||
|
||||
assert(detailedRelease, "Tried to access release before load");
|
||||
|
||||
return this.dependencies.toHelmRelease(detailedRelease.release);
|
||||
return detailedRelease.release;
|
||||
}
|
||||
|
||||
@computed private get details() {
|
||||
@ -227,7 +238,7 @@ export class ReleaseDetailsModel {
|
||||
|
||||
@computed get groupedResources(): MinimalResourceGroup[] {
|
||||
return pipeline(
|
||||
this.details?.resources ?? [],
|
||||
this.details.resources ?? [],
|
||||
groupBy((resource) => resource.kind),
|
||||
(grouped) => Object.entries(grouped),
|
||||
|
||||
|
@ -3,47 +3,57 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { HelmReleaseDto } from "../../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import requestHelmReleasesInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import type { HelmReleaseDetails } from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-details.injectable";
|
||||
import requestHelmReleaseDetailsInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-details.injectable";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import requestHelmReleaseInjectable from "../../../../../features/helm-releases/renderer/request–helm-release.injectable";
|
||||
import type { GetHelmReleaseArgs, HelmReleaseDataWithResources } from "../../../../../features/helm-releases/common/channels";
|
||||
import requestListHelmReleasesInjectable from "../../../../../features/helm-releases/renderer/request-list-helm-releases.injectable";
|
||||
import type { HelmRelease } from "../../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { toHelmRelease } from "../../to-helm-release";
|
||||
|
||||
export interface DetailedHelmRelease {
|
||||
release: HelmReleaseDto;
|
||||
details?: HelmReleaseDetails;
|
||||
release: HelmRelease;
|
||||
details: HelmReleaseDataWithResources;
|
||||
}
|
||||
|
||||
export type RequestDetailedHelmRelease = (
|
||||
name: string,
|
||||
namespace: string
|
||||
) => AsyncResult<DetailedHelmRelease>;
|
||||
export type RequestDetailedHelmRelease = (args: GetHelmReleaseArgs) => AsyncResult<DetailedHelmRelease>;
|
||||
|
||||
const requestDetailedHelmReleaseInjectable = getInjectable({
|
||||
id: "request-detailed-helm-release",
|
||||
|
||||
instantiate: (di): RequestDetailedHelmRelease => {
|
||||
const requestHelmReleases = di.inject(requestHelmReleasesInjectable);
|
||||
const requestHelmReleaseDetails = di.inject(requestHelmReleaseDetailsInjectable);
|
||||
const requestListHelmReleases = di.inject(requestListHelmReleasesInjectable);
|
||||
const requestHelmRelease = di.inject(requestHelmReleaseInjectable);
|
||||
|
||||
return async (name, namespace) => {
|
||||
const [releases, details] = await Promise.all([
|
||||
requestHelmReleases(namespace),
|
||||
requestHelmReleaseDetails(name, namespace),
|
||||
]);
|
||||
return async ({ clusterId, namespace, releaseName }) => {
|
||||
const listReleasesResult = await requestListHelmReleases({ clusterId, namespace });
|
||||
const detailsResult = await requestHelmRelease({ clusterId, releaseName, namespace });
|
||||
|
||||
const release = releases.find(
|
||||
(rel) => rel.name === name && rel.namespace === namespace,
|
||||
if (!listReleasesResult.callWasSuccessful) {
|
||||
return listReleasesResult;
|
||||
}
|
||||
|
||||
const release = listReleasesResult.response.find(
|
||||
(rel) => rel.name === releaseName && rel.namespace === namespace,
|
||||
);
|
||||
|
||||
if (!release) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Release ${name} didn't exist in ${namespace} namespace.`,
|
||||
error: `Release ${releaseName} didn't exist in ${namespace} namespace.`,
|
||||
};
|
||||
}
|
||||
|
||||
return { callWasSuccessful: true, response: { release, details }};
|
||||
if (!detailsResult.callWasSuccessful) {
|
||||
return detailsResult;
|
||||
}
|
||||
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: {
|
||||
release: toHelmRelease(release),
|
||||
details: detailsResult.response,
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -6,31 +6,49 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import releaseSecretsInjectable from "./release-secrets.injectable";
|
||||
import requestHelmReleasesInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable";
|
||||
import toHelmReleaseInjectable from "./to-helm-release.injectable";
|
||||
import requestListHelmReleasesInjectable from "../../../features/helm-releases/renderer/request-list-helm-releases.injectable";
|
||||
import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable";
|
||||
import assert from "assert";
|
||||
import { iter } from "@k8slens/utilities";
|
||||
import { prefixedLoggerInjectable } from "@k8slens/logger";
|
||||
import { toHelmRelease } from "./to-helm-release";
|
||||
|
||||
const releasesInjectable = getInjectable({
|
||||
id: "releases",
|
||||
|
||||
instantiate: (di) => {
|
||||
const clusterContext = di.inject(clusterFrameContextForNamespacedResourcesInjectable);
|
||||
const hostedClusterId = di.inject(hostedClusterIdInjectable);
|
||||
const releaseSecrets = di.inject(releaseSecretsInjectable);
|
||||
const requestHelmReleases = di.inject(requestHelmReleasesInjectable);
|
||||
const toHelmRelease = di.inject(toHelmReleaseInjectable);
|
||||
const requestListHelmReleases = di.inject(requestListHelmReleasesInjectable);
|
||||
const logger = di.inject(prefixedLoggerInjectable, "HELM-RELEASES");
|
||||
|
||||
assert(hostedClusterId, "hostedClusterId is required");
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async () => {
|
||||
void releaseSecrets.get();
|
||||
|
||||
const releaseArrays = await (
|
||||
const releaseResults = await (
|
||||
clusterContext.hasSelectedAll
|
||||
? requestHelmReleases()
|
||||
: Promise.all(clusterContext.contextNamespaces.map((namespace) => requestHelmReleases(namespace)))
|
||||
? requestListHelmReleases({ clusterId: hostedClusterId })
|
||||
: Promise.all(clusterContext.contextNamespaces.map((namespace) => requestListHelmReleases({ clusterId: hostedClusterId, namespace })))
|
||||
);
|
||||
|
||||
return releaseArrays.flat().map(toHelmRelease);
|
||||
},
|
||||
return iter.chain([releaseResults].flat().values())
|
||||
.filterMap((result) => {
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response;
|
||||
}
|
||||
|
||||
logger.warn("Failed to list helm releases", { error: result.error });
|
||||
|
||||
return undefined;
|
||||
})
|
||||
.flatMap((releases) => releases)
|
||||
.map(toHelmRelease)
|
||||
.toArray();
|
||||
},
|
||||
valueWhenPending: [],
|
||||
});
|
||||
},
|
||||
|
@ -1,90 +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 { capitalize } from "lodash";
|
||||
import { when } from "mobx";
|
||||
import helmChartVersionsInjectable from "../helm-charts/helm-charts/versions.injectable";
|
||||
import type { HelmRelease, HelmReleaseDto } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { getMillisecondsFromUnixEpoch } from "../../../common/utils/date/get-current-date-time";
|
||||
import { formatDuration } from "@k8slens/utilities";
|
||||
|
||||
export type ToHelmRelease = (release: HelmReleaseDto) => HelmRelease;
|
||||
|
||||
const toHelmReleaseInjectable = getInjectable({
|
||||
id: "to-helm-release",
|
||||
instantiate: (di): ToHelmRelease => {
|
||||
const helmChartVersions = (release: HelmRelease) => di.inject(helmChartVersionsInjectable, release);
|
||||
|
||||
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 = getMillisecondsFromUnixEpoch() - 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 versionsComputed = helmChartVersions(this);
|
||||
const version = this.getVersion();
|
||||
|
||||
await when(() => !versionsComputed.pending.get());
|
||||
|
||||
return versionsComputed.value
|
||||
.get()
|
||||
.find((chartVersion) => chartVersion.version === version)?.repo
|
||||
?? "";
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default toHelmReleaseInjectable;
|
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { capitalize } from "lodash";
|
||||
import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { getMillisecondsFromUnixEpoch } from "../../../common/utils/date/get-current-date-time";
|
||||
import { formatDuration } from "@k8slens/utilities";
|
||||
import type { ListedHelmRelease } from "../../../features/helm-releases/common/channels";
|
||||
|
||||
export const toHelmRelease = (release: ListedHelmRelease): HelmRelease => ({
|
||||
appVersion: release.app_version,
|
||||
chart: release.chart,
|
||||
namespace: release.namespace,
|
||||
revision: release.revision,
|
||||
status: release.status,
|
||||
name: release.name,
|
||||
updated: release.updated,
|
||||
|
||||
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 = getMillisecondsFromUnixEpoch() - updatedDate;
|
||||
|
||||
if (humanize) {
|
||||
return formatDuration(diff, compact);
|
||||
}
|
||||
|
||||
return diff;
|
||||
},
|
||||
});
|
@ -71,6 +71,7 @@ import { testUsingFakeTime } from "../../../test-utils/use-fake-time";
|
||||
import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
|
||||
import { getMessageBridgeFake } from "@k8slens/messaging-fake-bridge";
|
||||
import { historyInjectionToken } from "@k8slens/routing";
|
||||
import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable";
|
||||
|
||||
type MainDiCallback = (container: { mainDi: DiContainer }) => void | Promise<void>;
|
||||
type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise<void>;
|
||||
@ -240,7 +241,7 @@ export const getApplicationBuilder = () => {
|
||||
},
|
||||
}));
|
||||
|
||||
const windowHelpers = new Map<string, { di: DiContainer; getRendered: () => RenderResult }>();
|
||||
const windowHelpers: ApplicationWindowHelpers = new Map();
|
||||
|
||||
const createElectronWindowFake: CreateElectronWindow = (configuration) => {
|
||||
const windowId = configuration.id;
|
||||
@ -273,7 +274,10 @@ export const getApplicationBuilder = () => {
|
||||
|
||||
let rendered: RenderResult;
|
||||
|
||||
windowHelpers.set(windowId, { di: windowDi, getRendered: () => rendered });
|
||||
windowHelpers.set(windowId, {
|
||||
di: windowDi,
|
||||
getRendered: () => rendered,
|
||||
});
|
||||
|
||||
return {
|
||||
show: () => {},
|
||||
@ -321,9 +325,10 @@ export const getApplicationBuilder = () => {
|
||||
|
||||
const namespaceItems = observable.array<Namespace>();
|
||||
const selectedNamespaces = observable.set<string>();
|
||||
const startApplication = mainDi.inject(startApplicationInjectionToken);
|
||||
|
||||
const startApp = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => {
|
||||
const startApplication = mainDi.inject(startApplicationInjectionToken);
|
||||
|
||||
mainDi.inject(lensProxyPortInjectable).set(42);
|
||||
|
||||
for (const callback of beforeApplicationStartCallbacks) {
|
||||
@ -545,19 +550,17 @@ export const getApplicationBuilder = () => {
|
||||
setEnvironmentToClusterFrame: () => {
|
||||
environment = environments.clusterFrame;
|
||||
|
||||
const cluster = new Cluster({
|
||||
id: "some-cluster-id",
|
||||
contextName: "some-context-name",
|
||||
kubeConfigPath: "/some-path-to-kube-config",
|
||||
});
|
||||
|
||||
builder.beforeWindowStart(({ windowDi }) => {
|
||||
const cluster = new Cluster({
|
||||
id: "some-cluster-id",
|
||||
contextName: "some-context-name",
|
||||
kubeConfigPath: "/some-path-to-kube-config",
|
||||
});
|
||||
|
||||
windowDi.override(activeKubernetesClusterInjectable, () =>
|
||||
computed(() => catalogEntityFromCluster(cluster)),
|
||||
);
|
||||
|
||||
windowDi.override(hostedClusterIdInjectable, () => cluster.id);
|
||||
windowDi.override(hostedClusterInjectable, () => cluster);
|
||||
|
||||
// TODO: Remove this once we moved catalog to new IPC injectables
|
||||
windowDi.override(activeKubernetesClusterInjectable, () => computed(() => catalogEntityFromCluster(cluster)));
|
||||
|
||||
// TODO: Figure out a way to remove this stub.
|
||||
windowDi.override(namespaceStoreInjectable, () => ({
|
||||
@ -581,6 +584,43 @@ export const getApplicationBuilder = () => {
|
||||
} as Partial<NamespaceStore> as NamespaceStore));
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
const writeJsonSync = mainDi.inject(writeJsonSyncInjectable);
|
||||
|
||||
writeJsonSync("/some-path-to-kube-config", {
|
||||
clusters: [
|
||||
{
|
||||
name: cluster.contextName,
|
||||
},
|
||||
],
|
||||
users: [
|
||||
{
|
||||
name: "some-user-name",
|
||||
},
|
||||
],
|
||||
contexts: [
|
||||
{
|
||||
name: cluster.contextName,
|
||||
context: {
|
||||
cluster: cluster.contextName,
|
||||
user: "some-user-name",
|
||||
},
|
||||
},
|
||||
],
|
||||
"current-context": cluster.contextName,
|
||||
});
|
||||
writeJsonSync("/some-directory-for-app-data/some-product-name/lens-cluster-store.json", {
|
||||
clusters: [
|
||||
{
|
||||
id: cluster.id,
|
||||
kubeConfigPath: "/some-path-to-kube-config",
|
||||
contextName: cluster.contextName,
|
||||
},
|
||||
],
|
||||
__internal__: { migrations: { version: "6.4.0" }},
|
||||
});
|
||||
});
|
||||
|
||||
return builder;
|
||||
},
|
||||
|
||||
@ -774,17 +814,13 @@ const findExtensionInstance = <T extends LensExtension> (di: DiContainer, inject
|
||||
type ApplicationWindowHelpers = Map<string, { di: DiContainer; getRendered: () => RenderResult }>;
|
||||
|
||||
const toWindowWithHelpersFor =
|
||||
(windowHelpers: ApplicationWindowHelpers) => (applicationWindow: LensWindow) => ({
|
||||
(windowHelpers: ApplicationWindowHelpers) => (applicationWindow: LensWindow): LensWindowWithHelpers => ({
|
||||
...applicationWindow,
|
||||
|
||||
get rendered() {
|
||||
const helpers = windowHelpers.get(applicationWindow.id);
|
||||
|
||||
if (!helpers) {
|
||||
throw new Error(
|
||||
`Tried to get rendered for application window "${applicationWindow.id}" before it was started.`,
|
||||
);
|
||||
}
|
||||
assert(helpers, `Tried to get rendered for application window "${applicationWindow.id}" before it was started.`);
|
||||
|
||||
return helpers.getRendered();
|
||||
},
|
||||
@ -792,11 +828,7 @@ const toWindowWithHelpersFor =
|
||||
get di() {
|
||||
const helpers = windowHelpers.get(applicationWindow.id);
|
||||
|
||||
if (!helpers) {
|
||||
throw new Error(
|
||||
`Tried to get di for application window "${applicationWindow.id}" before it was started.`,
|
||||
);
|
||||
}
|
||||
assert(helpers, `Tried to get rendered for application window "${applicationWindow.id}" before it was started.`);
|
||||
|
||||
return helpers.di;
|
||||
},
|
||||
|
@ -49,7 +49,7 @@ const webpackLensMain = (): webpack.Configuration => {
|
||||
use: "node-loader",
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
test: (modulePath) => modulePath.endsWith(".ts") && !modulePath.endsWith(".test.ts"),
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "ts-loader",
|
||||
|
@ -62,7 +62,10 @@ export function webpackLensRenderer(): webpack.Configuration {
|
||||
use: "node-loader",
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
test: (modulePath) => (
|
||||
(modulePath.endsWith(".ts") && !modulePath.endsWith(".test.ts"))
|
||||
|| (modulePath.endsWith(".tsx") && !modulePath.endsWith(".test.tsx"))
|
||||
),
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "ts-loader",
|
||||
|
Loading…
Reference in New Issue
Block a user