mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Switch to non-reactive way of gettting possible helm release versions
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
5798f6722e
commit
18db8d544d
@ -3,11 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SemVer } from "semver";
|
||||
import semver, { coerce } from "semver";
|
||||
import * as iter from "./iter";
|
||||
import type { RawHelmChart } from "../k8s-api/endpoints/helm-charts.api";
|
||||
import logger from "../logger";
|
||||
|
||||
export enum Ordering {
|
||||
LESS = -1,
|
||||
@ -49,52 +45,31 @@ export function sortCompare<T>(left: T, right: T): Ordering {
|
||||
return Ordering.GREATER;
|
||||
}
|
||||
|
||||
interface ChartVersion {
|
||||
version: string;
|
||||
__version?: SemVer | null;
|
||||
}
|
||||
|
||||
export function sortCompareChartVersions(left: ChartVersion, right: ChartVersion): Ordering {
|
||||
if (left.__version && right.__version) {
|
||||
return semver.compare(right.__version, left.__version);
|
||||
}
|
||||
|
||||
if (!left.__version && right.__version) {
|
||||
return Ordering.GREATER;
|
||||
}
|
||||
|
||||
if (left.__version && !right.__version) {
|
||||
return Ordering.LESS;
|
||||
}
|
||||
|
||||
return sortCompare(left.version, right.version);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function sortCharts(charts: RawHelmChart[]) {
|
||||
interface ExtendedHelmChart extends RawHelmChart {
|
||||
__version?: SemVer | null;
|
||||
}
|
||||
|
||||
const chartsWithVersion = Array.from(
|
||||
iter.map(
|
||||
charts,
|
||||
chart => {
|
||||
const __version = coerce(chart.version, { loose: true });
|
||||
|
||||
if (!__version) {
|
||||
logger.warn(`[HELM-SERVICE]: Version from helm chart is not loosely coercable to semver.`, { name: chart.name, version: chart.version, repo: chart.repo });
|
||||
}
|
||||
|
||||
(chart as ExtendedHelmChart).__version = __version;
|
||||
|
||||
return chart as ExtendedHelmChart;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return chartsWithVersion
|
||||
.sort(sortCompareChartVersions)
|
||||
.map(chart => (delete chart.__version, chart as RawHelmChart));
|
||||
/**
|
||||
* This function sorts of list of items that have what should be a semver version formated string
|
||||
* as the field `version` but if it is not loosely coercable to semver falls back to sorting them
|
||||
* alphanumerically
|
||||
*/
|
||||
export function sortBySemverVersion<T extends { version: string }>(versioneds: T[]): T[] {
|
||||
return versioneds
|
||||
.map(versioned => ({
|
||||
__version: coerce(versioned.version, { loose: true }),
|
||||
raw: versioned,
|
||||
}))
|
||||
.sort((left, right) => {
|
||||
if (left.__version && right.__version) {
|
||||
return semver.compare(right.__version, left.__version);
|
||||
}
|
||||
|
||||
if (!left.__version && right.__version) {
|
||||
return Ordering.GREATER;
|
||||
}
|
||||
|
||||
if (left.__version && !right.__version) {
|
||||
return Ordering.LESS;
|
||||
}
|
||||
|
||||
return sortCompare(left.raw.version, right.raw.version);
|
||||
})
|
||||
.map(({ raw }) => raw);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import listHelmChartsInjectable from "../helm-service/list-helm-charts.injectabl
|
||||
import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
import type { AsyncResult } from "../../../common/utils/async-result";
|
||||
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
||||
import { sortCharts } from "../../../common/utils";
|
||||
import { sortBySemverVersion } from "../../../common/utils";
|
||||
import helmChartManagerInjectable from "../helm-chart-manager.injectable";
|
||||
|
||||
describe("Helm Service tests", () => {
|
||||
@ -203,7 +203,7 @@ describe("Helm Service tests", () => {
|
||||
|
||||
const charts = new Map([
|
||||
["stable", {
|
||||
"invalid-semver": sortCharts([
|
||||
"invalid-semver": sortBySemverVersion([
|
||||
{
|
||||
apiVersion: "3.0.0",
|
||||
name: "weird-versioning",
|
||||
@ -237,7 +237,7 @@ const charts = new Map([
|
||||
created: "now",
|
||||
},
|
||||
]),
|
||||
"apm-server": sortCharts([
|
||||
"apm-server": sortBySemverVersion([
|
||||
{
|
||||
apiVersion: "3.0.0",
|
||||
name: "apm-server",
|
||||
@ -255,7 +255,7 @@ const charts = new Map([
|
||||
created: "now",
|
||||
},
|
||||
]),
|
||||
"redis": sortCharts([
|
||||
"redis": sortBySemverVersion([
|
||||
{
|
||||
apiVersion: "3.0.0",
|
||||
name: "apm-server",
|
||||
@ -275,7 +275,7 @@ const charts = new Map([
|
||||
]),
|
||||
}],
|
||||
["experiment", {
|
||||
"fairwind": sortCharts([
|
||||
"fairwind": sortBySemverVersion([
|
||||
{
|
||||
apiVersion: "3.0.0",
|
||||
name: "fairwind",
|
||||
@ -296,7 +296,7 @@ const charts = new Map([
|
||||
]),
|
||||
}],
|
||||
["bitnami", {
|
||||
"hotdog": sortCharts([
|
||||
"hotdog": sortBySemverVersion([
|
||||
{
|
||||
apiVersion: "3.0.0",
|
||||
name: "hotdog",
|
||||
@ -314,7 +314,7 @@ const charts = new Map([
|
||||
created: "now",
|
||||
},
|
||||
]),
|
||||
"pretzel": sortCharts([
|
||||
"pretzel": sortBySemverVersion([
|
||||
{
|
||||
apiVersion: "3.0.0",
|
||||
name: "pretzel",
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
import fs from "fs";
|
||||
import * as yaml from "js-yaml";
|
||||
import { iter, put, sortCharts } from "../../common/utils";
|
||||
import { iter, put, sortBySemverVersion } from "../../common/utils";
|
||||
import { execHelm } from "./exec";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import { assert } from "console";
|
||||
@ -118,7 +118,7 @@ function normalizeHelmCharts(repoName: string, entries: RepoHelmChartList): Repo
|
||||
Object.entries(entries),
|
||||
([name, charts]) => [
|
||||
name,
|
||||
sortCharts(
|
||||
sortBySemverVersion(
|
||||
charts.map(chart => ({
|
||||
...chart,
|
||||
created: Date.parse(chart.created).toString(),
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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 { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api";
|
||||
import requestHelmChartVersionsInjectable from "../../../../common/k8s-api/endpoints/helm-charts.api/request-versions.injectable";
|
||||
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { sortBySemverVersion } from "../../../utils";
|
||||
import type { HelmChartVersion } from "./versions";
|
||||
|
||||
/**
|
||||
* @param release The release to try and figure out what chart versions match for
|
||||
* @param charts The list of possible helm charts that `release` could be of
|
||||
*/
|
||||
export type RequestVersionsOfHelmChart = (release: HelmRelease, charts: HelmChart[]) => Promise<HelmChartVersion[]>;
|
||||
|
||||
const requestVersionsOfHelmChartInjectable = getInjectable({
|
||||
id: "request-versions-of-helm-chart-for-helm-release-from-list-of-charts",
|
||||
instantiate: (di): RequestVersionsOfHelmChart => {
|
||||
const requestHelmChartVersions = di.inject(requestHelmChartVersionsInjectable);
|
||||
|
||||
return async (release, charts) => {
|
||||
const rawVersions = await Promise.all((
|
||||
charts
|
||||
.filter(chart => chart.getName() === release.getChart())
|
||||
.map(chart => chart.getRepository())
|
||||
.map(repo => requestHelmChartVersions(repo, release.getChart()))
|
||||
));
|
||||
|
||||
return sortBySemverVersion(rawVersions.flat());
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default requestVersionsOfHelmChartInjectable;
|
||||
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import requestHelmChartsInjectable from "../../../../common/k8s-api/endpoints/helm-charts.api/request-charts.injectable";
|
||||
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import requestVersionsOfHelmChartInjectable from "./request-versions-of-chart-for-release.injectable";
|
||||
import type { HelmChartVersion } from "./versions";
|
||||
|
||||
export type RequestVersionsOfHelmChartFor = (release: HelmRelease) => Promise<HelmChartVersion[]>;
|
||||
|
||||
const requestVersionsOfHelmChartForInjectable = getInjectable({
|
||||
id: "request-versions-of-helm-chart-for",
|
||||
instantiate: (di): RequestVersionsOfHelmChartFor => {
|
||||
const requestHelmCharts = di.inject(requestHelmChartsInjectable);
|
||||
const requestVersionsOfHelmChart = di.inject(requestVersionsOfHelmChartInjectable);
|
||||
|
||||
return async (release) => {
|
||||
const charts = await requestHelmCharts();
|
||||
|
||||
return requestVersionsOfHelmChart(release, charts);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default requestVersionsOfHelmChartForInjectable;
|
||||
|
||||
@ -5,40 +5,20 @@
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { when } from "mobx";
|
||||
import { coerce } from "semver";
|
||||
import requestHelmChartVersionsInjectable from "../../../../common/k8s-api/endpoints/helm-charts.api/request-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)
|
||||
);
|
||||
import requestVersionsOfHelmChartInjectable from "./request-versions-of-chart-for-release.injectable";
|
||||
|
||||
const helmChartVersionsInjectable = getInjectable({
|
||||
id: "helm-chart-versions-loader",
|
||||
instantiate: (di, release) => {
|
||||
const requestHelmChartVersions = di.inject(requestHelmChartVersionsInjectable);
|
||||
const helmCharts = di.inject(helmChartsInjectable);
|
||||
const requestVersionsOfHelmChart = di.inject(requestVersionsOfHelmChartInjectable);
|
||||
|
||||
return asyncComputed(async () => {
|
||||
await when(() => !helmCharts.pending.get());
|
||||
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());
|
||||
return requestVersionsOfHelmChart(release, helmCharts.value.get());
|
||||
}, []);
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
|
||||
12
src/renderer/components/+helm-charts/helm-charts/versions.ts
Normal file
12
src/renderer/components/+helm-charts/helm-charts/versions.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A type for the possible versions that a helm release was made from
|
||||
*/
|
||||
export interface HelmChartVersion {
|
||||
repo: string;
|
||||
version: string;
|
||||
}
|
||||
@ -7,7 +7,7 @@ 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 type { HelmChartVersion } from "../../+helm-charts/helm-charts/versions";
|
||||
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";
|
||||
@ -20,7 +20,7 @@ import upgradeChartTabStoreInjectable from "./store.injectable";
|
||||
|
||||
export interface UpgradeChartModel {
|
||||
readonly release: HelmRelease;
|
||||
readonly versionOptions: IComputedValue<SelectOption<ChartVersion>[]>;
|
||||
readonly versionOptions: IComputedValue<SelectOption<HelmChartVersion>[]>;
|
||||
readonly configration: {
|
||||
readonly value: IComputedValue<string>;
|
||||
set: (value: string) => void;
|
||||
@ -28,8 +28,8 @@ export interface UpgradeChartModel {
|
||||
setError: (error: unknown) => void;
|
||||
};
|
||||
readonly version: {
|
||||
readonly value: IComputedValue<ChartVersion | undefined>;
|
||||
set: (value: SingleValue<SelectOption<ChartVersion>>) => void;
|
||||
readonly value: IComputedValue<HelmChartVersion | undefined>;
|
||||
set: (value: SingleValue<SelectOption<HelmChartVersion>>) => void;
|
||||
};
|
||||
submit: () => Promise<UpgradeChartSubmitResult>;
|
||||
}
|
||||
@ -68,7 +68,7 @@ const upgradeChartModelInjectable = getInjectable({
|
||||
error: computed(() => configrationEditError.get()),
|
||||
setError: action((error) => configrationEditError.set(String(error))),
|
||||
};
|
||||
const versionValue = observable.box<ChartVersion>(undefined, {
|
||||
const versionValue = observable.box<HelmChartVersion>(undefined, {
|
||||
deep: false,
|
||||
});
|
||||
const version: UpgradeChartModel["version"] = {
|
||||
|
||||
@ -17,9 +17,9 @@ import { EditorPanel } from "../editor-panel";
|
||||
import type { SelectOption } from "../../select";
|
||||
import { Select } from "../../select";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { ChartVersion } from "../../+helm-charts/helm-charts/versions.injectable";
|
||||
import type { UpgradeChartModel } from "./upgrade-chart-model.injectable";
|
||||
import upgradeChartModelInjectable from "./upgrade-chart-model.injectable";
|
||||
import type { HelmChartVersion } from "../../+helm-charts/helm-charts/versions";
|
||||
|
||||
export interface UpgradeChartProps {
|
||||
className?: string;
|
||||
@ -82,7 +82,7 @@ export class NonInjectedUpgradeChart extends React.Component<UpgradeChartProps &
|
||||
{" "}
|
||||
<Badge label={release.getVersion()} />
|
||||
<span>Upgrade version</span>
|
||||
<Select<ChartVersion, SelectOption<ChartVersion>, false>
|
||||
<Select<HelmChartVersion, SelectOption<HelmChartVersion>, false>
|
||||
id="char-version-input"
|
||||
className="chart-version"
|
||||
menuPlacement="top"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user