Convert all of Helm functions to be DI

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton committed 2022-10-04 17:55:29 -04:00
1 parent 2f57644801
commit 83970fb5a4
62 files changed
+1513 -1570

No files matched your search

@@ -3,72 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { compile } from "path-to-regexp";
import { apiBase } from "../index";
import { stringify } from "querystring";
import type { RequestInit } from "node-fetch";
import { autoBind, bifurcateArray, isDefined } from "../../utils";
import { autoBind, bifurcateArray } from "../../utils";
import Joi from "joi";
export type RepoHelmChartList = Record<string, RawHelmChart[]>;
export interface IHelmChartDetails {
readme: string;
versions: HelmChart[];
}
const endpoint = compile(`/v2/charts/:repo?/:name?`) as (params?: {
repo?: string;
name?: string;
}) => string;
/**
* Get a list of all helm charts from all saved helm repos
*/
export async function listCharts(): Promise<HelmChart[]> {
const data = await apiBase.get<Record<string, RepoHelmChartList>>(endpoint());
return Object
.values(data)
.reduce((allCharts, repoCharts) => allCharts.concat(Object.values(repoCharts)), new Array<RawHelmChart[]>())
.map(([chart]) => HelmChart.create(chart, { onError: "log" }))
.filter(isDefined);
}
export interface GetChartDetailsOptions {
version?: string;
reqInit?: RequestInit;
}
/**
* Get the readme and all versions of a chart
* @param repo The repo to get from
* @param name The name of the chart to request the data of
* @param options.version The version of the chart's readme to get, default latest
* @param options.reqInit A way for passing in an abort controller or other browser request options
*/
export async function getChartDetails(repo: string, name: string, { version, reqInit }: GetChartDetailsOptions = {}): Promise<IHelmChartDetails> {
const path = endpoint({ repo, name });
const { readme, ...data } = await apiBase.get<IHelmChartDetails>(`${path}?${stringify({ version })}`, undefined, reqInit);
const versions = data.versions.map(version => HelmChart.create(version, { onError: "log" })).filter(isDefined);
return {
readme,
versions,
};
}
/**
* Get chart values related to a specific repos' version of a chart
* @param repo The repo to get from
* @param name The name of the chart to request the data of
* @param version The version to get the values from
*/
export async function getChartValues(repo: string, name: string, version: string): Promise<string> {
return apiBase.get<string>(`/v2/charts/${repo}/${name}/values?${stringify({ version })}`);
}
export interface RawHelmChart {
apiVersion: string;
name: string;
@@ -0,0 +1,24 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
const requestReadmeEndpoint = urlBuilderFor("/v2/charts/:repo/:name/readme");
export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => Promise<string>;
const requestHelmChartReadmeInjectable = getInjectable({
id: "request-helm-chart-readme",
instantiate: (di): RequestHelmChartReadme => {
const apiBase = di.inject(apiBaseInjectionToken);
return (repo, name, version) => (
apiBase.get(requestReadmeEndpoint.compile({ name, repo }, { version }))
);
},
});
export default requestHelmChartReadmeInjectable;
@@ -0,0 +1,24 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
const requestValuesEndpoint = urlBuilderFor("/v2/charts/:repo/:name/values");
export type RequestHelmChartValues = (repo: string, name: string, version: string) => Promise<string>;
const requestHelmChartValuesInjectable = getInjectable({
id: "request-helm-chart-values",
instantiate: (di): RequestHelmChartValues => {
const apiBase = di.inject(apiBaseInjectionToken);
return (repo, name, version) => (
apiBase.get(requestValuesEndpoint.compile({ repo, name }, { version }))
);
},
});
export default requestHelmChartValuesInjectable;
@@ -0,0 +1,31 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
import { HelmChart } from "../helm-charts.api";
import type { RawHelmChart } from "../helm-charts.api";
import { isDefined } from "../../../utils";
const requestVersionsEndpoint = urlBuilderFor("/v2/charts/:repo/:name/versions");
export type RequestHelmChartVersions = (repo: string, name: string) => Promise<HelmChart[]>;
const requestHelmChartVersionsInjectable = getInjectable({
id: "request-helm-chart-versions",
instantiate: (di): RequestHelmChartVersions => {
const apiBase = di.inject(apiBaseInjectionToken);
return async (repo, name) => {
const rawVersions = await apiBase.get(requestVersionsEndpoint.compile({ name, repo })) as RawHelmChart[];
return rawVersions
.map(version => HelmChart.create(version, { onError: "log" }))
.filter(isDefined);
};
},
});
export default requestHelmChartVersionsInjectable;
@@ -0,0 +1,34 @@
/**
* 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 { apiBaseInjectionToken } from "../../api-base";
import type { RawHelmChart } from "../helm-charts.api";
import { HelmChart } from "../helm-charts.api";
import { isDefined } from "../../../utils";
export type RequestHelmCharts = () => Promise<HelmChart[]>;
export type RepoHelmChartList = Record<string, RawHelmChart[]>;
/**
* Get a list of all helm charts from all saved helm repos
*/
const requestHelmChartsInjectable = getInjectable({
id: "request-helm-charts",
instantiate: (di) => {
const apiBase = di.inject(apiBaseInjectionToken);
return async () => {
const data = await apiBase.get<Record<string, RepoHelmChartList>>("/v2/charts");
return Object
.values(data)
.reduce((allCharts, repoCharts) => allCharts.concat(Object.values(repoCharts)), new Array<RawHelmChart[]>())
.map(([chart]) => HelmChart.create(chart, { onError: "log" }))
.filter(isDefined);
};
},
});
export default requestHelmChartsInjectable;
@@ -3,65 +3,14 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiBase } from "../index";
import type { ItemObject } from "../../item.store";
import type { JsonApiData } from "../json-api";
import { buildURLPositional } from "../../utils/buildUrl";
import type { HelmReleaseDetails } from "../../../renderer/components/+helm-releases/release-details/release-details-model/call-for-helm-release/call-for-helm-release-details/call-for-helm-release-details.injectable";
import type { HelmReleaseDetails } from "./helm-releases.api/get-details.injectable";
export interface HelmReleaseUpdateDetails {
log: string;
release: HelmReleaseDetails;
}
export interface HelmReleaseRevision {
revision: number;
updated: string;
status: string;
chart: string;
app_version: string;
description: string;
}
type EndpointParams = {}
| { namespace: string }
| { namespace: string; name: string }
| { namespace: string; name: string; route: string };
interface EndpointQuery {
all?: boolean;
}
export const endpoint = buildURLPositional<EndpointParams, EndpointQuery>("/v2/releases/:namespace?/:name?/:route?");
export async function deleteRelease(name: string, namespace: string): Promise<JsonApiData> {
const path = endpoint({ name, namespace });
return apiBase.del(path);
}
export async function getReleaseValues(name: string, namespace: string, all?: boolean): Promise<string> {
const route = "values";
const path = endpoint({ name, namespace, route }, { all });
return apiBase.get<string>(path);
}
export async function getReleaseHistory(name: string, namespace: string): Promise<HelmReleaseRevision[]> {
const route = "history";
const path = endpoint({ name, namespace, route });
return apiBase.get(path);
}
export async function rollbackRelease(name: string, namespace: string, revision: number): Promise<JsonApiData> {
const route = "rollback";
const path = endpoint({ name, namespace, route });
const data = { revision };
return apiBase.put(path, { data });
}
export interface HelmReleaseDto {
appVersion: string;
name: string;
@@ -0,0 +1,42 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import yaml from "js-yaml";
import { getInjectable } from "@ogre-tools/injectable";
import type { HelmReleaseUpdateDetails } from "../helm-releases.api";
import { apiBaseInjectionToken } from "../../api-base";
import { urlBuilderFor } from "../../../utils/buildUrl";
interface HelmReleaseCreatePayload {
name?: string;
repo: string;
chart: string;
namespace: string;
version: string;
values: string;
}
export type RequestCreateHelmRelease = (payload: HelmReleaseCreatePayload) => Promise<HelmReleaseUpdateDetails>;
const requestCreateEndpoint = urlBuilderFor("/v2/releases");
const requestCreateHelmReleaseInjectable = getInjectable({
id: "request-create-helm-release",
instantiate: (di): RequestCreateHelmRelease => {
const apiBase = di.inject(apiBaseInjectionToken);
return ({ repo, chart, values, ...data }) => {
return apiBase.post(requestCreateEndpoint.compile({}), {
data: {
chart: `${repo}/${chart}`,
values: yaml.load(values),
...data,
},
});
};
},
});
export default requestCreateHelmReleaseInjectable;
@@ -0,0 +1,22 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
export type RequestDeleteHelmRelease = (name: string, namespace: string) => Promise<void>;
const requestDeleteEndpoint = urlBuilderFor("/v2/releases/:namespace/:name");
const requestDeleteHelmReleaseInjectable = getInjectable({
id: "request-delete-helm-release",
instantiate: (di): RequestDeleteHelmRelease => {
const apiBase = di.inject(apiBaseInjectionToken);
return (name, namespace) => apiBase.del(requestDeleteEndpoint.compile({ name, namespace }));
},
});
export default requestDeleteHelmReleaseInjectable;
@@ -0,0 +1,31 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
export type RequestHelmReleaseConfiguration = (
name: string,
namespace: string,
all: boolean
) => Promise<string>;
const requestConfigurationEnpoint = urlBuilderFor("/v2/releases/:namespace/:name/values");
const requestHelmReleaseConfigurationInjectable = getInjectable({
id: "call-for-helm-release-configuration",
instantiate: (di): RequestHelmReleaseConfiguration => {
const apiBase = di.inject(apiBaseInjectionToken);
return (name, namespace, all: boolean) => (
apiBase.get(requestConfigurationEnpoint.compile({ name, namespace }, { all }))
);
},
causesSideEffects: true,
});
export default requestHelmReleaseConfigurationInjectable;
@@ -0,0 +1,41 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { KubeJsonApiData } from "../../kube-json-api";
import { apiBaseInjectionToken } from "../../api-base";
import { urlBuilderFor } from "../../../utils/buildUrl";
export interface HelmReleaseDetails {
resources: KubeJsonApiData[];
name: string;
namespace: string;
version: string;
config: string; // release values
manifest: string;
info: {
deleted: string;
description: string;
first_deployed: string;
last_deployed: string;
notes: string;
status: string;
};
}
export type CallForHelmReleaseDetails = (name: string, namespace: string) => Promise<HelmReleaseDetails>;
const requestDetailsEnpoint = urlBuilderFor("/v2/releases/:namespace/:name");
const requestHelmReleaseDetailsInjectable = getInjectable({
id: "call-for-helm-release-details",
instantiate: (di): CallForHelmReleaseDetails => {
const apiBase = di.inject(apiBaseInjectionToken);
return (name, namespace) => apiBase.get(requestDetailsEnpoint.compile({ name, namespace }));
},
});
export default requestHelmReleaseDetailsInjectable;
@@ -0,0 +1,31 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
export interface HelmReleaseRevision {
revision: number;
updated: string;
status: string;
chart: string;
app_version: string;
description: string;
}
export type RequestHelmReleaseHistory = (name: string, namespace: string) => Promise<HelmReleaseRevision[]>;
const requestHistoryEnpoint = urlBuilderFor("/v2/releases/:namespace/:name/history");
const requestHelmReleaseHistoryInjectable = getInjectable({
id: "request-helm-release-history",
instantiate: (di): RequestHelmReleaseHistory => {
const apiBase = di.inject(apiBaseInjectionToken);
return (name, namespace) => apiBase.get(requestHistoryEnpoint.compile({ name, namespace }));
},
});
export default requestHelmReleaseHistoryInjectable;
@@ -0,0 +1,22 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
export type RequestHelmReleaseValues = (name: string, namespace: string, all?: boolean) => Promise<string>;
const requestValuesEndpoint = urlBuilderFor("/v2/release/:namespace/:name/values");
const requestHelmReleaseValuesInjectable = getInjectable({
id: "request-helm-release-values",
instantiate: (di): RequestHelmReleaseValues => {
const apiBase = di.inject(apiBaseInjectionToken);
return (name, namespace, all) => apiBase.get(requestValuesEndpoint.compile({ name, namespace }, { all }));
},
});
export default requestHelmReleaseValuesInjectable;
@@ -0,0 +1,24 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
import type { HelmReleaseDto } from "../helm-releases.api";
export type RequestHelmReleases = (namespace?: string) => Promise<HelmReleaseDto[]>;
const requestHelmReleasesEndpoint = urlBuilderFor("/v2/releases/:namespace?");
const requestHelmReleasesInjectable = getInjectable({
id: "request-helm-releases",
instantiate: (di): RequestHelmReleases => {
const apiBase = di.inject(apiBaseInjectionToken);
return (namespace) => apiBase.get(requestHelmReleasesEndpoint.compile({ namespace }));
},
});
export default requestHelmReleasesInjectable;
@@ -0,0 +1,27 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { urlBuilderFor } from "../../../utils/buildUrl";
import { apiBaseInjectionToken } from "../../api-base";
export type RequestHelmReleaseRollback = (name: string, namespace: string, revision: number) => Promise<void>;
const requestRollbackEndpoint = urlBuilderFor("/v2/releases/:namespace/:name");
const requestHelmReleaseRollbackInjectable = getInjectable({
id: "request-helm-release-rollback",
instantiate: (di): RequestHelmReleaseRollback => {
const apiBase = di.inject(apiBaseInjectionToken);
return async (name, namespace, revision) => {
await apiBase.put(
requestRollbackEndpoint.compile({ name, namespace }),
{ data: { revision }},
);
};
},
});
export default requestHelmReleaseRollbackInjectable;
@@ -0,0 +1,49 @@
/**
* 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 yaml from "js-yaml";
import { apiBaseInjectionToken } from "../../api-base";
import { urlBuilderFor } from "../../../utils/buildUrl";
interface HelmReleaseUpdatePayload {
repo: string;
chart: string;
version: string;
values: string;
}
export type RequestHelmReleaseUpdate = (
name: string,
namespace: string,
payload: HelmReleaseUpdatePayload
) => Promise<{ updateWasSuccessful: true } | { updateWasSuccessful: false; error: unknown }>;
const requestUpdateEndpoint = urlBuilderFor("/v2/releases/:namespace/:name");
const requestHelmReleaseUpdateInjectable = getInjectable({
id: "request-helm-release-update",
instantiate: (di): RequestHelmReleaseUpdate => {
const apiBase = di.inject(apiBaseInjectionToken);
return async (name, namespace, { repo, chart, values, ...data }) => {
try {
await apiBase.put(requestUpdateEndpoint.compile({ name, namespace }), {
data: {
chart: `${repo}/${chart}`,
values: yaml.load(values),
...data,
},
});
} catch (e) {
return { updateWasSuccessful: false, error: e };
}
return { updateWasSuccessful: true };
};
},
});
export default requestHelmReleaseUpdateInjectable;