mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix showing-details-for-helm-release behavioural tests
- Remove HelmChartStore in favour of all injectables - Create a model for UpgradeChartDockTab Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
4bef236f8c
commit
042b679ca6
@ -434,14 +434,8 @@ exports[`opening dock tab for installing helm chart given application is started
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="NoItems flex box grow"
|
class="Spinner singleColor center"
|
||||||
>
|
/>
|
||||||
<div
|
|
||||||
class="box center"
|
|
||||||
>
|
|
||||||
Item list is empty
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="AddRemoveButtons flex gaps"
|
class="AddRemoveButtons flex gaps"
|
||||||
|
|||||||
@ -12295,8 +12295,147 @@ exports[`showing details for helm release given application is started when navi
|
|||||||
style="flex-basis: 300px;"
|
style="flex-basis: 300px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="Spinner singleColor center"
|
class="UpgradeChart flex column"
|
||||||
/>
|
>
|
||||||
|
<div
|
||||||
|
class="InfoPanel flex gaps align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="controls"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="upgrade flex gaps align-center"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Release
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="badge"
|
||||||
|
>
|
||||||
|
some-name
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
Namespace
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="badge"
|
||||||
|
>
|
||||||
|
some-namespace
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
Version
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="badge"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
Upgrade version
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class="Select theme-outlined chart-version css-b62m3t-container"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="css-1f43avz-a11yText-A11yText"
|
||||||
|
id="react-select-char-version-input-live-region"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
aria-atomic="false"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-relevant="additions text"
|
||||||
|
class="css-1f43avz-a11yText-A11yText"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="Select__control css-1s2u09g-control"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Select__value-container css-319lph-ValueContainer"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Select__placeholder css-14el2xx-placeholder"
|
||||||
|
id="react-select-char-version-input-placeholder"
|
||||||
|
>
|
||||||
|
Select...
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Select__input-container css-6j8wv5-Input"
|
||||||
|
data-value=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-describedby="react-select-char-version-input-placeholder"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-haspopup="true"
|
||||||
|
autocapitalize="none"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
class="Select__input"
|
||||||
|
id="char-version-input"
|
||||||
|
role="combobox"
|
||||||
|
spellcheck="false"
|
||||||
|
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||||
|
tabindex="0"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="css-tj5bde-Svg"
|
||||||
|
focusable="false"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex gaps align-center"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="Button plain"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="Button active outlined"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Upgrade
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="Button primary active"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Upgrade & Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
data-testid="monaco-editor-for-some-tab-id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -23,6 +23,14 @@ import requestHelmReleaseInjectable from "../../renderer/components/+helm-releas
|
|||||||
import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable";
|
import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable";
|
||||||
import showCheckedErrorInjectable from "../../renderer/components/notifications/show-checked-error.injectable";
|
import showCheckedErrorInjectable from "../../renderer/components/notifications/show-checked-error.injectable";
|
||||||
import getRandomUpgradeChartTabIdInjectable from "../../renderer/components/dock/upgrade-chart/get-random-upgrade-chart-tab-id.injectable";
|
import getRandomUpgradeChartTabIdInjectable from "../../renderer/components/dock/upgrade-chart/get-random-upgrade-chart-tab-id.injectable";
|
||||||
|
import type { RequestHelmCharts } from "../../common/k8s-api/endpoints/helm-charts.api/list.injectable";
|
||||||
|
import type { RequestHelmChartVersions } from "../../common/k8s-api/endpoints/helm-charts.api/get-versions.injectable";
|
||||||
|
import type { RequestHelmChartReadme } from "../../common/k8s-api/endpoints/helm-charts.api/get-readme.injectable";
|
||||||
|
import type { RequestHelmChartValues } from "../../common/k8s-api/endpoints/helm-charts.api/get-values.injectable";
|
||||||
|
import requestHelmChartsInjectable from "../../common/k8s-api/endpoints/helm-charts.api/list.injectable";
|
||||||
|
import requestHelmChartVersionsInjectable from "../../common/k8s-api/endpoints/helm-charts.api/get-versions.injectable";
|
||||||
|
import requestHelmChartReadmeInjectable from "../../common/k8s-api/endpoints/helm-charts.api/get-readme.injectable";
|
||||||
|
import requestHelmChartValuesInjectable from "../../common/k8s-api/endpoints/helm-charts.api/get-values.injectable";
|
||||||
|
|
||||||
describe("showing details for helm release", () => {
|
describe("showing details for helm release", () => {
|
||||||
let builder: ApplicationBuilder;
|
let builder: ApplicationBuilder;
|
||||||
@ -30,6 +38,10 @@ describe("showing details for helm release", () => {
|
|||||||
let requestHelmReleaseMock: AsyncFnMock<RequestHelmRelease>;
|
let requestHelmReleaseMock: AsyncFnMock<RequestHelmRelease>;
|
||||||
let requestHelmReleaseConfigurationMock: AsyncFnMock<RequestHelmReleaseConfiguration>;
|
let requestHelmReleaseConfigurationMock: AsyncFnMock<RequestHelmReleaseConfiguration>;
|
||||||
let requestHelmReleaseUpdateMock: AsyncFnMock<RequestHelmReleaseUpdate>;
|
let requestHelmReleaseUpdateMock: AsyncFnMock<RequestHelmReleaseUpdate>;
|
||||||
|
let requestHelmChartsMock: AsyncFnMock<RequestHelmCharts>;
|
||||||
|
let requestHelmChartVersionsMock: AsyncFnMock<RequestHelmChartVersions>;
|
||||||
|
let requestHelmChartReadmeMock: AsyncFnMock<RequestHelmChartReadme>;
|
||||||
|
let requestHelmChartValuesMock: AsyncFnMock<RequestHelmChartValues>;
|
||||||
let showSuccessNotificationMock: jest.Mock;
|
let showSuccessNotificationMock: jest.Mock;
|
||||||
let showCheckedErrorNotificationMock: jest.Mock;
|
let showCheckedErrorNotificationMock: jest.Mock;
|
||||||
|
|
||||||
@ -44,6 +56,10 @@ describe("showing details for helm release", () => {
|
|||||||
requestHelmReleaseMock = asyncFn();
|
requestHelmReleaseMock = asyncFn();
|
||||||
requestHelmReleaseConfigurationMock = asyncFn();
|
requestHelmReleaseConfigurationMock = asyncFn();
|
||||||
requestHelmReleaseUpdateMock = asyncFn();
|
requestHelmReleaseUpdateMock = asyncFn();
|
||||||
|
requestHelmChartsMock = asyncFn();
|
||||||
|
requestHelmChartVersionsMock = asyncFn();
|
||||||
|
requestHelmChartReadmeMock = asyncFn();
|
||||||
|
requestHelmChartValuesMock = asyncFn();
|
||||||
|
|
||||||
showSuccessNotificationMock = jest.fn();
|
showSuccessNotificationMock = jest.fn();
|
||||||
showCheckedErrorNotificationMock = jest.fn();
|
showCheckedErrorNotificationMock = jest.fn();
|
||||||
@ -56,6 +72,10 @@ describe("showing details for helm release", () => {
|
|||||||
windowDi.override(requestHelmReleaseInjectable, () => requestHelmReleaseMock);
|
windowDi.override(requestHelmReleaseInjectable, () => requestHelmReleaseMock);
|
||||||
windowDi.override(requestHelmReleaseConfigurationInjectable, () => requestHelmReleaseConfigurationMock);
|
windowDi.override(requestHelmReleaseConfigurationInjectable, () => requestHelmReleaseConfigurationMock);
|
||||||
windowDi.override(requestHelmReleaseUpdateInjectable, () => requestHelmReleaseUpdateMock);
|
windowDi.override(requestHelmReleaseUpdateInjectable, () => requestHelmReleaseUpdateMock);
|
||||||
|
windowDi.override(requestHelmChartsInjectable, () => requestHelmChartsMock);
|
||||||
|
windowDi.override(requestHelmChartVersionsInjectable, () => requestHelmChartVersionsMock);
|
||||||
|
windowDi.override(requestHelmChartReadmeInjectable, () => requestHelmChartReadmeMock);
|
||||||
|
windowDi.override(requestHelmChartValuesInjectable, () => requestHelmChartValuesMock);
|
||||||
windowDi.override(
|
windowDi.override(
|
||||||
namespaceStoreInjectable,
|
namespaceStoreInjectable,
|
||||||
() =>
|
() =>
|
||||||
@ -449,6 +469,16 @@ describe("showing details for helm release", () => {
|
|||||||
expect(rendered.baseElement).toMatchSnapshot();
|
expect(rendered.baseElement).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("shows spinner", () => {
|
||||||
|
const saveButton = rendered.getByTestId(
|
||||||
|
"helm-release-configuration-save-button",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(saveButton).toHaveClass("waiting");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
it("calls for update", () => {
|
it("calls for update", () => {
|
||||||
expect(requestHelmReleaseUpdateMock).toHaveBeenCalledWith(
|
expect(requestHelmReleaseUpdateMock).toHaveBeenCalledWith(
|
||||||
"some-name",
|
"some-name",
|
||||||
@ -463,14 +493,6 @@ describe("showing details for helm release", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows spinner", () => {
|
|
||||||
const saveButton = rendered.getByTestId(
|
|
||||||
"helm-release-configuration-save-button",
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(saveButton).toHaveClass("waiting");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when update resolves with success", () => {
|
describe("when update resolves with success", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
requestHelmReleasesMock.mockClear();
|
requestHelmReleasesMock.mockClear();
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getGlobalOverride } from "../../../common/test-utils/get-global-override";
|
||||||
|
import getHelmChartReadmeInjectable from "./get-helm-chart-readme.injectable";
|
||||||
|
|
||||||
|
export default getGlobalOverride(getHelmChartReadmeInjectable, () => () => {
|
||||||
|
throw new Error("tried to get a helm chart's readme without overriding");
|
||||||
|
});
|
||||||
@ -20,8 +20,7 @@ import navigateToHelmChartsInjectable from "../../../common/front-end-routing/ro
|
|||||||
import { HelmChartIcon } from "./icon";
|
import { HelmChartIcon } from "./icon";
|
||||||
import helmChartsInjectable from "./helm-charts/helm-charts.injectable";
|
import helmChartsInjectable from "./helm-charts/helm-charts.injectable";
|
||||||
import selectedHelmChartInjectable from "./helm-charts/selected-helm-chart.injectable";
|
import selectedHelmChartInjectable from "./helm-charts/selected-helm-chart.injectable";
|
||||||
import type { HelmChartStore } from "./store";
|
import { noop } from "lodash";
|
||||||
import helmChartStoreInjectable from "./store.injectable";
|
|
||||||
|
|
||||||
enum columnId {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
@ -39,7 +38,6 @@ interface Dependencies {
|
|||||||
navigateToHelmCharts: NavigateToHelmCharts;
|
navigateToHelmCharts: NavigateToHelmCharts;
|
||||||
charts: IAsyncComputed<HelmChart[]>;
|
charts: IAsyncComputed<HelmChart[]>;
|
||||||
selectedChart: IComputedValue<HelmChart | undefined>;
|
selectedChart: IComputedValue<HelmChart | undefined>;
|
||||||
helmChartStore: HelmChartStore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -69,17 +67,31 @@ class NonInjectedHelmCharts extends Component<Dependencies> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { charts } = this.props;
|
||||||
const selectedChart = this.props.selectedChart.get();
|
const selectedChart = this.props.selectedChart.get();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SiblingsInTabLayout>
|
<SiblingsInTabLayout>
|
||||||
<div data-testid="page-for-helm-charts" style={{ display: "none" }}/>
|
<div data-testid="page-for-helm-charts" style={{ display: "none" }}/>
|
||||||
|
|
||||||
<ItemListLayout
|
<ItemListLayout<HelmChart, false>
|
||||||
isConfigurable
|
isConfigurable
|
||||||
tableId="helm_charts"
|
tableId="helm_charts"
|
||||||
className="HelmCharts"
|
className="HelmCharts"
|
||||||
store={this.props.helmChartStore}
|
store={{
|
||||||
|
get isLoaded() {
|
||||||
|
return !charts.pending.get();
|
||||||
|
},
|
||||||
|
failedLoading: false,
|
||||||
|
getTotalCount: () => charts.value.get().length,
|
||||||
|
isSelected: (item) => item === selectedChart,
|
||||||
|
toggleSelection: noop,
|
||||||
|
isSelectedAll: () => false,
|
||||||
|
toggleSelectionAll: () => false,
|
||||||
|
pickOnlySelected: () => [],
|
||||||
|
removeSelectedItems: async () => {},
|
||||||
|
}}
|
||||||
|
preloadStores={false}
|
||||||
getItems={() => this.props.charts.value.get()}
|
getItems={() => this.props.charts.value.get()}
|
||||||
isSelectable={false}
|
isSelectable={false}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
@ -138,8 +150,6 @@ export const HelmCharts = withInjectables<Dependencies>(NonInjectedHelmCharts, {
|
|||||||
navigateToHelmCharts: di.inject(navigateToHelmChartsInjectable),
|
navigateToHelmCharts: di.inject(navigateToHelmChartsInjectable),
|
||||||
charts: di.inject(helmChartsInjectable),
|
charts: di.inject(helmChartsInjectable),
|
||||||
selectedChart: di.inject(selectedHelmChartInjectable),
|
selectedChart: di.inject(selectedHelmChartInjectable),
|
||||||
helmChartStore: di.inject(helmChartStoreInjectable),
|
|
||||||
}),
|
}),
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* 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 { coerce } from "semver";
|
||||||
|
import requestHelmChartVersionsInjectable from "../../../../common/k8s-api/endpoints/helm-charts.api/get-versions.injectable";
|
||||||
|
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||||
|
import { sortCompareChartVersions } from "../../../utils";
|
||||||
|
import helmChartsInjectable from "./helm-charts.injectable";
|
||||||
|
|
||||||
|
export interface ChartVersion {
|
||||||
|
repo: string;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortChartVersions = (versions: ChartVersion[]) => (
|
||||||
|
versions
|
||||||
|
.map(chartVersion => ({ ...chartVersion, __version: coerce(chartVersion.version, { loose: true }) }))
|
||||||
|
.sort(sortCompareChartVersions)
|
||||||
|
.map(({ __version, ...chartVersion }) => chartVersion)
|
||||||
|
);
|
||||||
|
|
||||||
|
const helmChartVersionsInjectable = getInjectable({
|
||||||
|
id: "helm-chart-versions-loader",
|
||||||
|
instantiate: (di, release) => {
|
||||||
|
const requestHelmChartVersions = di.inject(requestHelmChartVersionsInjectable);
|
||||||
|
const helmCharts = di.inject(helmChartsInjectable);
|
||||||
|
|
||||||
|
return asyncComputed(async () => {
|
||||||
|
const rawVersions = await Promise.all((
|
||||||
|
helmCharts.value.get()
|
||||||
|
.filter(chart => chart.getName() === release.getChart())
|
||||||
|
.map(chart => chart.getRepository())
|
||||||
|
.map(repo => requestHelmChartVersions(repo, release.getChart()))
|
||||||
|
));
|
||||||
|
|
||||||
|
return sortChartVersions(rawVersions.flat());
|
||||||
|
}, []);
|
||||||
|
},
|
||||||
|
lifecycle: lifecycleEnum.keyedSingleton({
|
||||||
|
getInstanceKey: (di, release: HelmRelease) => release.getName(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default helmChartVersionsInjectable;
|
||||||
@ -1,18 +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 requestHelmChartVersionsInjectable from "../../../common/k8s-api/endpoints/helm-charts.api/get-versions.injectable";
|
|
||||||
import requestHelmChartsInjectable from "../../../common/k8s-api/endpoints/helm-charts.api/list.injectable";
|
|
||||||
import { HelmChartStore } from "./store";
|
|
||||||
|
|
||||||
const helmChartStoreInjectable = getInjectable({
|
|
||||||
id: "helm-chart-store",
|
|
||||||
instantiate: (di) => new HelmChartStore({
|
|
||||||
requestHelmCharts: di.inject(requestHelmChartsInjectable),
|
|
||||||
requestHelmChartVersions: di.inject(requestHelmChartVersionsInjectable),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default helmChartStoreInjectable;
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import semver from "semver";
|
|
||||||
import { observable, makeObservable } from "mobx";
|
|
||||||
import { autoBind, sortCompareChartVersions } from "../../utils";
|
|
||||||
import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api";
|
|
||||||
import { ItemStore } from "../../../common/item.store";
|
|
||||||
import flatten from "lodash/flatten";
|
|
||||||
import type { RequestHelmCharts } from "../../../common/k8s-api/endpoints/helm-charts.api/list.injectable";
|
|
||||||
import type { RequestHelmChartVersions } from "../../../common/k8s-api/endpoints/helm-charts.api/get-versions.injectable";
|
|
||||||
|
|
||||||
export interface ChartVersion {
|
|
||||||
repo: string;
|
|
||||||
version: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Dependencies {
|
|
||||||
requestHelmCharts: RequestHelmCharts;
|
|
||||||
requestHelmChartVersions: RequestHelmChartVersions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HelmChartStore extends ItemStore<HelmChart> {
|
|
||||||
@observable versions = observable.map<string, ChartVersion[]>();
|
|
||||||
|
|
||||||
constructor(protected readonly dependencies: Dependencies) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
makeObservable(this);
|
|
||||||
autoBind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadAll() {
|
|
||||||
try {
|
|
||||||
const res = await this.loadItems(() => this.dependencies.requestHelmCharts());
|
|
||||||
|
|
||||||
this.failedLoading = false;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
} catch (error) {
|
|
||||||
this.failedLoading = true;
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getByName(name: string, repo?: string) {
|
|
||||||
if (typeof repo !== "string") {
|
|
||||||
/**
|
|
||||||
* FIXME:
|
|
||||||
* This is here because in strict mode `getByName` MUST be 100% compatiable if called in the
|
|
||||||
* situation where it is only a "ItemStore"
|
|
||||||
*/
|
|
||||||
throw new TypeError("repo must be provided");
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.items.find(chart => chart.getName() === name && chart.getRepository() === repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected sortVersions = (versions: ChartVersion[]) => {
|
|
||||||
return versions
|
|
||||||
.map(chartVersion => ({ ...chartVersion, __version: semver.coerce(chartVersion.version, { loose: true }) }))
|
|
||||||
.sort(sortCompareChartVersions)
|
|
||||||
.map(({ __version, ...chartVersion }) => chartVersion);
|
|
||||||
};
|
|
||||||
|
|
||||||
async getVersions(chartName: string, force?: boolean): Promise<ChartVersion[]> {
|
|
||||||
const versions = this.versions.get(chartName);
|
|
||||||
|
|
||||||
if (versions && !force) {
|
|
||||||
return versions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadVersions = async (repo: string) => {
|
|
||||||
const versions = await this.dependencies.requestHelmChartVersions(repo, chartName);
|
|
||||||
|
|
||||||
return versions.map(chart => ({
|
|
||||||
repo,
|
|
||||||
version: chart.getVersion(),
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!this.isLoaded) {
|
|
||||||
await this.loadAll();
|
|
||||||
}
|
|
||||||
const repos = this.items
|
|
||||||
.filter(chart => chart.getName() === chartName)
|
|
||||||
.map(chart => chart.getRepository());
|
|
||||||
|
|
||||||
const newVersions = await Promise.all(repos.map(loadVersions))
|
|
||||||
.then(flatten)
|
|
||||||
.then(this.sortVersions);
|
|
||||||
|
|
||||||
this.versions.set(chartName, newVersions);
|
|
||||||
|
|
||||||
return newVersions;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
super.reset();
|
|
||||||
this.versions.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Not supported
|
|
||||||
*/
|
|
||||||
removeItems(): Promise<void> {
|
|
||||||
throw new Error("removeItems is not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,7 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { capitalize } from "lodash";
|
import { capitalize } from "lodash";
|
||||||
import helmChartStoreInjectable from "../+helm-charts/store.injectable";
|
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 type { HelmRelease, HelmReleaseDto } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||||
import { formatDuration } from "../../utils";
|
import { formatDuration } from "../../utils";
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ export type ToHelmRelease = (release: HelmReleaseDto) => HelmRelease;
|
|||||||
const toHelmReleaseInjectable = getInjectable({
|
const toHelmReleaseInjectable = getInjectable({
|
||||||
id: "to-helm-release",
|
id: "to-helm-release",
|
||||||
instantiate: (di): ToHelmRelease => {
|
instantiate: (di): ToHelmRelease => {
|
||||||
const helmChartStore = di.inject(helmChartStoreInjectable);
|
const helmChartVersions = (release: HelmRelease) => di.inject(helmChartVersionsInjectable, release);
|
||||||
|
|
||||||
return (release) => ({
|
return (release) => ({
|
||||||
...release,
|
...release,
|
||||||
@ -71,14 +72,14 @@ const toHelmReleaseInjectable = getInjectable({
|
|||||||
// Helm does not store from what repository the release is installed,
|
// Helm does not store from what repository the release is installed,
|
||||||
// so we have to try to guess it by searching charts
|
// so we have to try to guess it by searching charts
|
||||||
async getRepo() {
|
async getRepo() {
|
||||||
const chartName = this.getChart();
|
const versionsComputed = helmChartVersions(this);
|
||||||
const version = this.getVersion();
|
|
||||||
const versions = await helmChartStore.getVersions(chartName);
|
|
||||||
const chartVersion = versions.find(
|
|
||||||
(chartVersion) => chartVersion.version === version,
|
|
||||||
);
|
|
||||||
|
|
||||||
return chartVersion ? chartVersion.repo : "";
|
await when(() => !versionsComputed.pending.get());
|
||||||
|
|
||||||
|
const version = this.getVersion();
|
||||||
|
const versions = versionsComputed.value.get();
|
||||||
|
|
||||||
|
return versions.find((chartVersion) => chartVersion.version === version)?.repo ?? "";
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,23 +3,27 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import type { IChartUpgradeData } from "./store.injectable";
|
||||||
import upgradeChartTabStoreInjectable from "./store.injectable";
|
import upgradeChartTabStoreInjectable from "./store.injectable";
|
||||||
import dockStoreInjectable from "../dock/store.injectable";
|
import dockStoreInjectable from "../dock/store.injectable";
|
||||||
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||||
import type { DockStore, DockTabCreateSpecific, TabId } from "../dock/store";
|
import type { DockStore, DockTabCreateSpecific, TabId } from "../dock/store";
|
||||||
import { TabKind } from "../dock/store";
|
import { TabKind } from "../dock/store";
|
||||||
import type { UpgradeChartTabStore } from "./store";
|
|
||||||
import { runInAction } from "mobx";
|
import { runInAction } from "mobx";
|
||||||
import getRandomUpgradeChartTabIdInjectable from "./get-random-upgrade-chart-tab-id.injectable";
|
import getRandomUpgradeChartTabIdInjectable from "./get-random-upgrade-chart-tab-id.injectable";
|
||||||
|
import type { DockTabStore } from "../dock-tab-store/dock-tab.store";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
upgradeChartStore: UpgradeChartTabStore;
|
upgradeChartStore: DockTabStore<IChartUpgradeData>;
|
||||||
dockStore: DockStore;
|
dockStore: DockStore;
|
||||||
getRandomId: () => string;
|
getRandomId: () => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createUpgradeChartTab = ({ upgradeChartStore, dockStore, getRandomId }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateSpecific = {}): TabId => {
|
const createUpgradeChartTab = ({ upgradeChartStore, dockStore, getRandomId }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateSpecific = {}): TabId => {
|
||||||
const tabId = upgradeChartStore.getTabIdByRelease(release.getName());
|
const tabId = upgradeChartStore.findTabIdFromData(val => (
|
||||||
|
val.releaseName === release.getName()
|
||||||
|
&& val.releaseNamespace === release.getNs()
|
||||||
|
));
|
||||||
|
|
||||||
if (tabId) {
|
if (tabId) {
|
||||||
dockStore.open();
|
dockStore.open();
|
||||||
|
|||||||
@ -3,10 +3,12 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { UpgradeChartTabStore } from "./store";
|
|
||||||
import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable";
|
import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable";
|
||||||
import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable";
|
|
||||||
import requestHelmReleaseConfigurationInjectable from "../../../../common/k8s-api/endpoints/helm-releases.api/get-configuration.injectable";
|
export interface IChartUpgradeData {
|
||||||
|
releaseName: string;
|
||||||
|
releaseNamespace: string;
|
||||||
|
}
|
||||||
|
|
||||||
const upgradeChartTabStoreInjectable = getInjectable({
|
const upgradeChartTabStoreInjectable = getInjectable({
|
||||||
id: "upgrade-chart-tab-store",
|
id: "upgrade-chart-tab-store",
|
||||||
@ -14,10 +16,8 @@ const upgradeChartTabStoreInjectable = getInjectable({
|
|||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const createDockTabStore = di.inject(createDockTabStoreInjectable);
|
const createDockTabStore = di.inject(createDockTabStoreInjectable);
|
||||||
|
|
||||||
return new UpgradeChartTabStore({
|
return createDockTabStore<IChartUpgradeData>({
|
||||||
createStorage: di.inject(createStorageInjectable),
|
storageKey: "chart_releases",
|
||||||
valuesStore: createDockTabStore<string>(),
|
|
||||||
requestHelmReleaseConfiguration: di.inject(requestHelmReleaseConfigurationInjectable),
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { action, computed, makeObservable } from "mobx";
|
|
||||||
import type { TabId } from "../dock/store";
|
|
||||||
import type { DockTabStoreDependencies } from "../dock-tab-store/dock-tab.store";
|
|
||||||
import { DockTabStore } from "../dock-tab-store/dock-tab.store";
|
|
||||||
import assert from "assert";
|
|
||||||
import type { RequestHelmReleaseConfiguration } from "../../../../common/k8s-api/endpoints/helm-releases.api/get-configuration.injectable";
|
|
||||||
|
|
||||||
export interface IChartUpgradeData {
|
|
||||||
releaseName: string;
|
|
||||||
releaseNamespace: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpgradeChartTabStoreDependencies extends DockTabStoreDependencies {
|
|
||||||
valuesStore: DockTabStore<string>;
|
|
||||||
requestHelmReleaseConfiguration: RequestHelmReleaseConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UpgradeChartTabStore extends DockTabStore<IChartUpgradeData> {
|
|
||||||
@computed private get releaseNameReverseLookup(): Map<string, string> {
|
|
||||||
return new Map(this.getAllData().map(([id, { releaseName }]) => [releaseName, id]));
|
|
||||||
}
|
|
||||||
|
|
||||||
get values() {
|
|
||||||
return this.dependencies.valuesStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(protected readonly dependencies: UpgradeChartTabStoreDependencies) {
|
|
||||||
super(dependencies, {
|
|
||||||
storageKey: "chart_releases",
|
|
||||||
});
|
|
||||||
|
|
||||||
makeObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
async reloadValues(tabId: TabId) {
|
|
||||||
this.values.clearData(tabId); // reset
|
|
||||||
const data = this.getData(tabId);
|
|
||||||
|
|
||||||
assert(data, "cannot reload values if no data");
|
|
||||||
|
|
||||||
const { releaseName, releaseNamespace } = data;
|
|
||||||
const values = await this.dependencies.requestHelmReleaseConfiguration(releaseName, releaseNamespace, true);
|
|
||||||
|
|
||||||
this.values.setData(tabId, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTabIdByRelease(releaseName: string) {
|
|
||||||
return this.releaseNameReverseLookup.get(releaseName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* 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 type { IComputedValue } from "mobx";
|
||||||
|
import { action, computed, observable, when } from "mobx";
|
||||||
|
import type { SingleValue } from "react-select";
|
||||||
|
import type { ChartVersion } from "../../+helm-charts/helm-charts/versions.injectable";
|
||||||
|
import helmChartVersionsInjectable from "../../+helm-charts/helm-charts/versions.injectable";
|
||||||
|
import releasesInjectable from "../../+helm-releases/releases.injectable";
|
||||||
|
import updateReleaseInjectable from "../../+helm-releases/update-release/update-release.injectable";
|
||||||
|
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||||
|
import requestHelmReleaseConfigurationInjectable from "../../../../common/k8s-api/endpoints/helm-releases.api/get-configuration.injectable";
|
||||||
|
import { waitUntilDefined } from "../../../utils";
|
||||||
|
import type { SelectOption } from "../../select";
|
||||||
|
import type { DockTab } from "../dock/store";
|
||||||
|
import upgradeChartTabStoreInjectable from "./store.injectable";
|
||||||
|
|
||||||
|
export interface UpgradeChartModel {
|
||||||
|
readonly release: HelmRelease;
|
||||||
|
readonly versionOptions: IComputedValue<SelectOption<ChartVersion>[]>;
|
||||||
|
readonly configration: {
|
||||||
|
readonly value: IComputedValue<string>;
|
||||||
|
set: (value: string) => void;
|
||||||
|
readonly error: IComputedValue<string | undefined>;
|
||||||
|
setError: (error: unknown) => void;
|
||||||
|
};
|
||||||
|
readonly version: {
|
||||||
|
readonly value: IComputedValue<ChartVersion | undefined>;
|
||||||
|
set: (value: SingleValue<SelectOption<ChartVersion>>) => void;
|
||||||
|
};
|
||||||
|
submit: () => Promise<UpgradeChartSubmitResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpgradeChartSubmitResult {
|
||||||
|
completedSuccessfully: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const upgradeChartModelInjectable = getInjectable({
|
||||||
|
id: "upgrade-chart-model",
|
||||||
|
instantiate: async (di, tab): Promise<UpgradeChartModel> => {
|
||||||
|
const upgradeChartTabStore = di.inject(upgradeChartTabStoreInjectable);
|
||||||
|
const releases = di.inject(releasesInjectable);
|
||||||
|
const requestHelmReleaseConfiguration = di.inject(requestHelmReleaseConfigurationInjectable);
|
||||||
|
const updateRelease = di.inject(updateReleaseInjectable);
|
||||||
|
|
||||||
|
const tabData = await waitUntilDefined(() => upgradeChartTabStore.getData(tab.id));
|
||||||
|
const release = await waitUntilDefined(() => releases.value.get().find(release => release.getName() === tabData.releaseName));
|
||||||
|
const versions = di.inject(helmChartVersionsInjectable, release);
|
||||||
|
const storedConfigration = asyncComputed(() => requestHelmReleaseConfiguration(
|
||||||
|
release.getName(),
|
||||||
|
release.getNs(),
|
||||||
|
true,
|
||||||
|
), "");
|
||||||
|
|
||||||
|
await when(() => !versions.pending.get());
|
||||||
|
|
||||||
|
const configrationValue = observable.box<string>();
|
||||||
|
const configrationEditError = observable.box<string>();
|
||||||
|
const configration: UpgradeChartModel["configration"] = {
|
||||||
|
value: computed(() => configrationValue.get() ?? storedConfigration.value.get()),
|
||||||
|
set: action((value) => {
|
||||||
|
configrationValue.set(value);
|
||||||
|
configrationEditError.set(undefined);
|
||||||
|
}),
|
||||||
|
error: computed(() => configrationEditError.get()),
|
||||||
|
setError: action((error) => configrationEditError.set(String(error))),
|
||||||
|
};
|
||||||
|
const versionValue = observable.box<ChartVersion | undefined>(versions.value.get()[0]);
|
||||||
|
const version: UpgradeChartModel["version"] = {
|
||||||
|
value: computed(() => versionValue.get()),
|
||||||
|
set: action((option) => versionValue.set(option?.value)),
|
||||||
|
};
|
||||||
|
const versionOptions = computed(() => (
|
||||||
|
versions.value
|
||||||
|
.get()
|
||||||
|
.map(version => ({
|
||||||
|
value: version,
|
||||||
|
label: `${version.repo}/${release.getChart()}-${version.version}`,
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
|
||||||
|
return {
|
||||||
|
release,
|
||||||
|
versionOptions,
|
||||||
|
configration,
|
||||||
|
version,
|
||||||
|
submit: async () => {
|
||||||
|
const version = versionValue.get();
|
||||||
|
|
||||||
|
if (!version || configrationEditError.get()) {
|
||||||
|
return {
|
||||||
|
completedSuccessfully: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateRelease(
|
||||||
|
release.getName(),
|
||||||
|
release.getNs(),
|
||||||
|
{
|
||||||
|
chart: release.getChart(),
|
||||||
|
values: configration.value.get(),
|
||||||
|
...version,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
storedConfigration.invalidate();
|
||||||
|
|
||||||
|
return {
|
||||||
|
completedSuccessfully: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
lifecycle: lifecycleEnum.keyedSingleton({
|
||||||
|
getInstanceKey: (di, tab: DockTab) => tab.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default upgradeChartModelInjectable;
|
||||||
@ -6,27 +6,20 @@
|
|||||||
import "./upgrade-chart.scss";
|
import "./upgrade-chart.scss";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { action, makeObservable, observable, reaction } from "mobx";
|
import { makeObservable, observable } from "mobx";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { cssNames } from "../../../utils";
|
import { cssNames } from "../../../utils";
|
||||||
import type { DockTab } from "../dock/store";
|
import type { DockTab } from "../dock/store";
|
||||||
import { InfoPanel } from "../info-panel";
|
import { InfoPanel } from "../info-panel";
|
||||||
import type { UpgradeChartTabStore } from "./store";
|
|
||||||
import { Spinner } from "../../spinner";
|
import { Spinner } from "../../spinner";
|
||||||
import { Badge } from "../../badge";
|
import { Badge } from "../../badge";
|
||||||
import { EditorPanel } from "../editor-panel";
|
import { EditorPanel } from "../editor-panel";
|
||||||
import type { HelmChartStore, ChartVersion } from "../../+helm-charts/store";
|
|
||||||
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
|
||||||
import type { SelectOption } from "../../select";
|
import type { SelectOption } from "../../select";
|
||||||
import { Select } from "../../select";
|
import { Select } from "../../select";
|
||||||
import type { IAsyncComputed } from "@ogre-tools/injectable-react";
|
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import upgradeChartTabStoreInjectable from "./store.injectable";
|
import type { ChartVersion } from "../../+helm-charts/helm-charts/versions.injectable";
|
||||||
import updateReleaseInjectable from "../../+helm-releases/update-release/update-release.injectable";
|
import type { UpgradeChartModel } from "./upgrade-chart-model.injectable";
|
||||||
import releasesInjectable from "../../+helm-releases/releases.injectable";
|
import upgradeChartModelInjectable from "./upgrade-chart-model.injectable";
|
||||||
import type { RequestHelmReleaseUpdate } from "../../../../common/k8s-api/endpoints/helm-releases.api/update.injectable";
|
|
||||||
import { first } from "lodash/fp";
|
|
||||||
import helmChartStoreInjectable from "../../+helm-charts/store.injectable";
|
|
||||||
|
|
||||||
export interface UpgradeChartProps {
|
export interface UpgradeChartProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -34,160 +27,78 @@ export interface UpgradeChartProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
releases: IAsyncComputed<HelmRelease[]>;
|
model: UpgradeChartModel;
|
||||||
upgradeChartTabStore: UpgradeChartTabStore;
|
|
||||||
updateRelease: RequestHelmReleaseUpdate;
|
|
||||||
helmChartStore: HelmChartStore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class NonInjectedUpgradeChart extends React.Component<UpgradeChartProps & Dependencies> {
|
export class NonInjectedUpgradeChart extends React.Component<UpgradeChartProps & Dependencies> {
|
||||||
@observable error?: string;
|
@observable error?: string;
|
||||||
@observable versions = observable.array<ChartVersion>();
|
|
||||||
@observable version: ChartVersion | undefined = undefined;
|
|
||||||
|
|
||||||
constructor(props: UpgradeChartProps & Dependencies) {
|
constructor(props: UpgradeChartProps & Dependencies) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
disposeOnUnmount(this, [
|
|
||||||
reaction(
|
|
||||||
() => this.release,
|
|
||||||
release => this.reloadVersions(release),
|
|
||||||
{
|
|
||||||
fireImmediately: true,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
reaction(
|
|
||||||
() => this.release?.getRevision(),
|
|
||||||
() => this.reloadValues(),
|
|
||||||
{
|
|
||||||
fireImmediately: true,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
get tabId() {
|
|
||||||
return this.props.tab.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
get release() {
|
|
||||||
const tabData = this.props.upgradeChartTabStore.getData(this.tabId);
|
|
||||||
|
|
||||||
if (!tabData) return null;
|
|
||||||
|
|
||||||
return this.props.releases.value.get().find(release => release.getName() === tabData.releaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
get value() {
|
|
||||||
return this.props.upgradeChartTabStore.values.getData(this.tabId);
|
|
||||||
}
|
|
||||||
|
|
||||||
async reloadValues() {
|
|
||||||
this.props.upgradeChartTabStore.reloadValues(this.props.tab.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async reloadVersions(release: HelmRelease | null | undefined) {
|
|
||||||
if (!release) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.version = undefined;
|
|
||||||
this.versions.clear();
|
|
||||||
const versions = await this.props.helmChartStore.getVersions(release.getChart());
|
|
||||||
|
|
||||||
this.versions.replace(versions);
|
|
||||||
this.version = first(this.versions);
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange = action((value: string) => {
|
|
||||||
this.error = "";
|
|
||||||
this.props.upgradeChartTabStore.values.setData(this.tabId, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
onError = action((error: Error | string) => {
|
|
||||||
this.error = error.toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
upgrade = async () => {
|
upgrade = async () => {
|
||||||
if (this.error || !this.release || !this.version || !this.value) {
|
const { model } = this.props;
|
||||||
return null;
|
const { completedSuccessfully } = await model.submit();
|
||||||
|
|
||||||
|
if (completedSuccessfully) {
|
||||||
|
return (
|
||||||
|
<p>
|
||||||
|
{"Release "}
|
||||||
|
<b>{model.release.getName()}</b>
|
||||||
|
{" successfully upgraded to version "}
|
||||||
|
<b>{model.version.value.get()}</b>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { version, repo } = this.version;
|
return null;
|
||||||
const releaseName = this.release.getName();
|
|
||||||
const releaseNs = this.release.getNs();
|
|
||||||
|
|
||||||
await this.props.updateRelease(releaseName, releaseNs, {
|
|
||||||
chart: this.release.getChart(),
|
|
||||||
values: this.value,
|
|
||||||
repo, version,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<p>
|
|
||||||
{"Release "}
|
|
||||||
<b>{releaseName}</b>
|
|
||||||
{" successfully upgraded to version "}
|
|
||||||
<b>{version}</b>
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { tabId, release, value, error, onChange, onError, upgrade, versions, version } = this;
|
const { model, className, tab } = this.props;
|
||||||
const { className } = this.props;
|
const tabId = tab.id;
|
||||||
|
const { release } = model;
|
||||||
if (!release || !this.props.upgradeChartTabStore.isReady(tabId) || !version) {
|
|
||||||
return <Spinner center />;
|
|
||||||
}
|
|
||||||
const currentVersion = release.getVersion();
|
|
||||||
const versionOptions = versions.map(version => ({
|
|
||||||
value: version,
|
|
||||||
label: `${version.repo}/${release.getChart()}-${version.version}`,
|
|
||||||
}));
|
|
||||||
const controlsAndInfo = (
|
|
||||||
<div className="upgrade flex gaps align-center">
|
|
||||||
<span>Release</span>
|
|
||||||
{" "}
|
|
||||||
<Badge label={release.getName()} />
|
|
||||||
<span>Namespace</span>
|
|
||||||
{" "}
|
|
||||||
<Badge label={release.getNs()} />
|
|
||||||
<span>Version</span>
|
|
||||||
{" "}
|
|
||||||
<Badge label={currentVersion} />
|
|
||||||
<span>Upgrade version</span>
|
|
||||||
<Select<ChartVersion, SelectOption<ChartVersion>, false>
|
|
||||||
id="char-version-input"
|
|
||||||
className="chart-version"
|
|
||||||
menuPlacement="top"
|
|
||||||
themeName="outlined"
|
|
||||||
value={version}
|
|
||||||
options={versionOptions}
|
|
||||||
onChange={option => this.version = option?.value}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cssNames("UpgradeChart flex column", className)}>
|
<div className={cssNames("UpgradeChart flex column", className)}>
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
tabId={tabId}
|
tabId={tabId}
|
||||||
error={error}
|
error={model.configration.error.get()}
|
||||||
submit={upgrade}
|
submit={this.upgrade}
|
||||||
submitLabel="Upgrade"
|
submitLabel="Upgrade"
|
||||||
submittingMessage="Updating.."
|
submittingMessage="Updating.."
|
||||||
controls={controlsAndInfo}
|
controls={(
|
||||||
|
<div className="upgrade flex gaps align-center">
|
||||||
|
<span>Release</span>
|
||||||
|
{" "}
|
||||||
|
<Badge label={release.getName()} />
|
||||||
|
<span>Namespace</span>
|
||||||
|
{" "}
|
||||||
|
<Badge label={release.getNs()} />
|
||||||
|
<span>Version</span>
|
||||||
|
{" "}
|
||||||
|
<Badge label={model.version.value.get()} />
|
||||||
|
<span>Upgrade version</span>
|
||||||
|
<Select<ChartVersion, SelectOption<ChartVersion>, false>
|
||||||
|
id="char-version-input"
|
||||||
|
className="chart-version"
|
||||||
|
menuPlacement="top"
|
||||||
|
themeName="outlined"
|
||||||
|
value={model.version.value.get()}
|
||||||
|
options={model.versionOptions.get()}
|
||||||
|
onChange={model.version.set}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<EditorPanel
|
<EditorPanel
|
||||||
tabId={tabId}
|
tabId={tabId}
|
||||||
value={value ?? ""}
|
value={model.configration.value.get()}
|
||||||
onChange={onChange}
|
onChange={model.configration.set}
|
||||||
onError={onError}
|
onError={model.configration.setError}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -195,11 +106,9 @@ export class NonInjectedUpgradeChart extends React.Component<UpgradeChartProps &
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const UpgradeChart = withInjectables<Dependencies, UpgradeChartProps>(NonInjectedUpgradeChart, {
|
export const UpgradeChart = withInjectables<Dependencies, UpgradeChartProps>(NonInjectedUpgradeChart, {
|
||||||
getProps: (di, props) => ({
|
getPlaceholder: () => <Spinner center />,
|
||||||
|
getProps: async (di, props) => ({
|
||||||
...props,
|
...props,
|
||||||
releases: di.inject(releasesInjectable),
|
model: await di.inject(upgradeChartModelInjectable, props.tab),
|
||||||
updateRelease: di.inject(updateReleaseInjectable),
|
|
||||||
upgradeChartTabStore: di.inject(upgradeChartTabStoreInjectable),
|
|
||||||
helmChartStore: di.inject(helmChartStoreInjectable),
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user