Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Do not crash when opening details of a helm release #7697

Merged
merged 2 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,25 @@
*/

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;
chart: string;
status: string;
updated: string;
revision: string;
}

export interface HelmRelease extends HelmReleaseDto, ItemObject {
getNs: () => string;
getChart: (withVersion?: boolean) => string;
getRevision: () => number;
getStatus: () => string;
getVersion: () => string;
getUpdated: (humanize?: boolean, compact?: boolean) => string | number;
getRepo: () => Promise<string>;
}

This file was deleted.

This file was deleted.

15 changes: 5 additions & 10 deletions packages/core/src/features/cluster/workloads/pods.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type { PodMetricsApi } from "../../../common/k8s-api/endpoints/pod-metric
import podMetricsApiInjectable from "../../../common/k8s-api/endpoints/pod-metrics.api.injectable";
import type { RequestMetrics } from "../../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";
import requestMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";

describe("workloads / pods", () => {
let rendered: RenderResult;
Expand All @@ -24,19 +23,15 @@ describe("workloads / pods", () => {
applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame();
applicationBuilder.namespaces.add("default");
applicationBuilder.beforeWindowStart(({ windowDi }) => {
windowDi.override(podMetricsApiInjectable, () => ({
list: async () => Promise.resolve(podMetrics),
} as PodMetricsApi));
});
applicationBuilder.afterWindowStart(() => {
applicationBuilder.allowKubeResource({
apiName: "pods",
group: "",
});

windowDi.override(podMetricsApiInjectable, () => ({
list: async () => Promise.resolve(podMetrics),
} as PodMetricsApi));

const apiManager = windowDi.inject(apiManagerInjectable);
const podStore = windowDi.inject(podStoreInjectable);

apiManager.registerStore(podStore);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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");
Expand All @@ -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
Expand All @@ -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");
});
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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";
Expand All @@ -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 () => {
Expand All @@ -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);

Expand All @@ -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");
Expand Down Expand Up @@ -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", () => {
Expand Down
59 changes: 59 additions & 0 deletions packages/core/src/features/helm-releases/common/channels.ts
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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;
Loading