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.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { SemVer } from "semver";
|
|
||||||
import semver, { coerce } 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 {
|
export enum Ordering {
|
||||||
LESS = -1,
|
LESS = -1,
|
||||||
@ -49,52 +45,31 @@ export function sortCompare<T>(left: T, right: T): Ordering {
|
|||||||
return Ordering.GREATER;
|
return Ordering.GREATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ChartVersion {
|
/**
|
||||||
version: string;
|
* This function sorts of list of items that have what should be a semver version formated string
|
||||||
__version?: SemVer | null;
|
* as the field `version` but if it is not loosely coercable to semver falls back to sorting them
|
||||||
}
|
* alphanumerically
|
||||||
|
*/
|
||||||
export function sortCompareChartVersions(left: ChartVersion, right: ChartVersion): Ordering {
|
export function sortBySemverVersion<T extends { version: string }>(versioneds: T[]): T[] {
|
||||||
if (left.__version && right.__version) {
|
return versioneds
|
||||||
return semver.compare(right.__version, left.__version);
|
.map(versioned => ({
|
||||||
}
|
__version: coerce(versioned.version, { loose: true }),
|
||||||
|
raw: versioned,
|
||||||
if (!left.__version && right.__version) {
|
}))
|
||||||
return Ordering.GREATER;
|
.sort((left, right) => {
|
||||||
}
|
if (left.__version && right.__version) {
|
||||||
|
return semver.compare(right.__version, left.__version);
|
||||||
if (left.__version && !right.__version) {
|
}
|
||||||
return Ordering.LESS;
|
|
||||||
}
|
if (!left.__version && right.__version) {
|
||||||
|
return Ordering.GREATER;
|
||||||
return sortCompare(left.version, right.version);
|
}
|
||||||
}
|
|
||||||
|
if (left.__version && !right.__version) {
|
||||||
|
return Ordering.LESS;
|
||||||
|
}
|
||||||
export function sortCharts(charts: RawHelmChart[]) {
|
|
||||||
interface ExtendedHelmChart extends RawHelmChart {
|
return sortCompare(left.raw.version, right.raw.version);
|
||||||
__version?: SemVer | null;
|
})
|
||||||
}
|
.map(({ raw }) => raw);
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||||
import type { AsyncResult } from "../../../common/utils/async-result";
|
import type { AsyncResult } from "../../../common/utils/async-result";
|
||||||
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
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";
|
import helmChartManagerInjectable from "../helm-chart-manager.injectable";
|
||||||
|
|
||||||
describe("Helm Service tests", () => {
|
describe("Helm Service tests", () => {
|
||||||
@ -203,7 +203,7 @@ describe("Helm Service tests", () => {
|
|||||||
|
|
||||||
const charts = new Map([
|
const charts = new Map([
|
||||||
["stable", {
|
["stable", {
|
||||||
"invalid-semver": sortCharts([
|
"invalid-semver": sortBySemverVersion([
|
||||||
{
|
{
|
||||||
apiVersion: "3.0.0",
|
apiVersion: "3.0.0",
|
||||||
name: "weird-versioning",
|
name: "weird-versioning",
|
||||||
@ -237,7 +237,7 @@ const charts = new Map([
|
|||||||
created: "now",
|
created: "now",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
"apm-server": sortCharts([
|
"apm-server": sortBySemverVersion([
|
||||||
{
|
{
|
||||||
apiVersion: "3.0.0",
|
apiVersion: "3.0.0",
|
||||||
name: "apm-server",
|
name: "apm-server",
|
||||||
@ -255,7 +255,7 @@ const charts = new Map([
|
|||||||
created: "now",
|
created: "now",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
"redis": sortCharts([
|
"redis": sortBySemverVersion([
|
||||||
{
|
{
|
||||||
apiVersion: "3.0.0",
|
apiVersion: "3.0.0",
|
||||||
name: "apm-server",
|
name: "apm-server",
|
||||||
@ -275,7 +275,7 @@ const charts = new Map([
|
|||||||
]),
|
]),
|
||||||
}],
|
}],
|
||||||
["experiment", {
|
["experiment", {
|
||||||
"fairwind": sortCharts([
|
"fairwind": sortBySemverVersion([
|
||||||
{
|
{
|
||||||
apiVersion: "3.0.0",
|
apiVersion: "3.0.0",
|
||||||
name: "fairwind",
|
name: "fairwind",
|
||||||
@ -296,7 +296,7 @@ const charts = new Map([
|
|||||||
]),
|
]),
|
||||||
}],
|
}],
|
||||||
["bitnami", {
|
["bitnami", {
|
||||||
"hotdog": sortCharts([
|
"hotdog": sortBySemverVersion([
|
||||||
{
|
{
|
||||||
apiVersion: "3.0.0",
|
apiVersion: "3.0.0",
|
||||||
name: "hotdog",
|
name: "hotdog",
|
||||||
@ -314,7 +314,7 @@ const charts = new Map([
|
|||||||
created: "now",
|
created: "now",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
"pretzel": sortCharts([
|
"pretzel": sortBySemverVersion([
|
||||||
{
|
{
|
||||||
apiVersion: "3.0.0",
|
apiVersion: "3.0.0",
|
||||||
name: "pretzel",
|
name: "pretzel",
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import * as yaml from "js-yaml";
|
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 { execHelm } from "./exec";
|
||||||
import type { SetRequired } from "type-fest";
|
import type { SetRequired } from "type-fest";
|
||||||
import { assert } from "console";
|
import { assert } from "console";
|
||||||
@ -118,7 +118,7 @@ function normalizeHelmCharts(repoName: string, entries: RepoHelmChartList): Repo
|
|||||||
Object.entries(entries),
|
Object.entries(entries),
|
||||||
([name, charts]) => [
|
([name, charts]) => [
|
||||||
name,
|
name,
|
||||||
sortCharts(
|
sortBySemverVersion(
|
||||||
charts.map(chart => ({
|
charts.map(chart => ({
|
||||||
...chart,
|
...chart,
|
||||||
created: Date.parse(chart.created).toString(),
|
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 { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||||
import { when } from "mobx";
|
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 type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||||
import { sortCompareChartVersions } from "../../../utils";
|
|
||||||
import helmChartsInjectable from "./helm-charts.injectable";
|
import helmChartsInjectable from "./helm-charts.injectable";
|
||||||
|
import requestVersionsOfHelmChartInjectable from "./request-versions-of-chart-for-release.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({
|
const helmChartVersionsInjectable = getInjectable({
|
||||||
id: "helm-chart-versions-loader",
|
id: "helm-chart-versions-loader",
|
||||||
instantiate: (di, release) => {
|
instantiate: (di, release) => {
|
||||||
const requestHelmChartVersions = di.inject(requestHelmChartVersionsInjectable);
|
|
||||||
const helmCharts = di.inject(helmChartsInjectable);
|
const helmCharts = di.inject(helmChartsInjectable);
|
||||||
|
const requestVersionsOfHelmChart = di.inject(requestVersionsOfHelmChartInjectable);
|
||||||
|
|
||||||
return asyncComputed(async () => {
|
return asyncComputed(async () => {
|
||||||
await when(() => !helmCharts.pending.get());
|
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({
|
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 type { IComputedValue } from "mobx";
|
||||||
import { action, computed, observable, when } from "mobx";
|
import { action, computed, observable, when } from "mobx";
|
||||||
import type { SingleValue } from "react-select";
|
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 helmChartVersionsInjectable from "../../+helm-charts/helm-charts/versions.injectable";
|
||||||
import releasesInjectable from "../../+helm-releases/releases.injectable";
|
import releasesInjectable from "../../+helm-releases/releases.injectable";
|
||||||
import updateReleaseInjectable from "../../+helm-releases/update-release/update-release.injectable";
|
import updateReleaseInjectable from "../../+helm-releases/update-release/update-release.injectable";
|
||||||
@ -20,7 +20,7 @@ import upgradeChartTabStoreInjectable from "./store.injectable";
|
|||||||
|
|
||||||
export interface UpgradeChartModel {
|
export interface UpgradeChartModel {
|
||||||
readonly release: HelmRelease;
|
readonly release: HelmRelease;
|
||||||
readonly versionOptions: IComputedValue<SelectOption<ChartVersion>[]>;
|
readonly versionOptions: IComputedValue<SelectOption<HelmChartVersion>[]>;
|
||||||
readonly configration: {
|
readonly configration: {
|
||||||
readonly value: IComputedValue<string>;
|
readonly value: IComputedValue<string>;
|
||||||
set: (value: string) => void;
|
set: (value: string) => void;
|
||||||
@ -28,8 +28,8 @@ export interface UpgradeChartModel {
|
|||||||
setError: (error: unknown) => void;
|
setError: (error: unknown) => void;
|
||||||
};
|
};
|
||||||
readonly version: {
|
readonly version: {
|
||||||
readonly value: IComputedValue<ChartVersion | undefined>;
|
readonly value: IComputedValue<HelmChartVersion | undefined>;
|
||||||
set: (value: SingleValue<SelectOption<ChartVersion>>) => void;
|
set: (value: SingleValue<SelectOption<HelmChartVersion>>) => void;
|
||||||
};
|
};
|
||||||
submit: () => Promise<UpgradeChartSubmitResult>;
|
submit: () => Promise<UpgradeChartSubmitResult>;
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ const upgradeChartModelInjectable = getInjectable({
|
|||||||
error: computed(() => configrationEditError.get()),
|
error: computed(() => configrationEditError.get()),
|
||||||
setError: action((error) => configrationEditError.set(String(error))),
|
setError: action((error) => configrationEditError.set(String(error))),
|
||||||
};
|
};
|
||||||
const versionValue = observable.box<ChartVersion>(undefined, {
|
const versionValue = observable.box<HelmChartVersion>(undefined, {
|
||||||
deep: false,
|
deep: false,
|
||||||
});
|
});
|
||||||
const version: UpgradeChartModel["version"] = {
|
const version: UpgradeChartModel["version"] = {
|
||||||
|
|||||||
@ -17,9 +17,9 @@ import { EditorPanel } from "../editor-panel";
|
|||||||
import type { SelectOption } from "../../select";
|
import type { SelectOption } from "../../select";
|
||||||
import { Select } from "../../select";
|
import { Select } from "../../select";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
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 type { UpgradeChartModel } from "./upgrade-chart-model.injectable";
|
||||||
import upgradeChartModelInjectable from "./upgrade-chart-model.injectable";
|
import upgradeChartModelInjectable from "./upgrade-chart-model.injectable";
|
||||||
|
import type { HelmChartVersion } from "../../+helm-charts/helm-charts/versions";
|
||||||
|
|
||||||
export interface UpgradeChartProps {
|
export interface UpgradeChartProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -82,7 +82,7 @@ export class NonInjectedUpgradeChart extends React.Component<UpgradeChartProps &
|
|||||||
{" "}
|
{" "}
|
||||||
<Badge label={release.getVersion()} />
|
<Badge label={release.getVersion()} />
|
||||||
<span>Upgrade version</span>
|
<span>Upgrade version</span>
|
||||||
<Select<ChartVersion, SelectOption<ChartVersion>, false>
|
<Select<HelmChartVersion, SelectOption<HelmChartVersion>, false>
|
||||||
id="char-version-input"
|
id="char-version-input"
|
||||||
className="chart-version"
|
className="chart-version"
|
||||||
menuPlacement="top"
|
menuPlacement="top"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user