mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Stop using HelmCli from Renderer (#4861)
* Introduce way for execute file Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make typing of HelmRepo shared Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce way to get Helm environment values Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce function to read YAML file Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for listing active helm repositories in preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make sense in name of injectable Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce helper for opening and selecting values of select Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for activating, deactivating public helm repositories in preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for deactivating helm repository from list of active repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add missing global overrides Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make some tests more deterministic by mocking tooltips Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for activating custom helm repository in preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove old implementation made redundant with competition for preferences of helm repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add success notification for activating custom helm repository Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce way to get single active helm repository Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract responsibilities from god-class and switch to getting helm repositories using competition instead of another god class Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add TODO Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak position of spinner Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Start handling errors when accessing helm repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Handle error about no helm repositories when updating repositories Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove unwarranted function configuration Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add missing global overrides Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove duplication how to acquire binary path for helm Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove redundant comment Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate naming to match Helm's internal Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Relocate file closer to it's relatives Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
1 parent
5420780ae0
commit
1393cc303d
99 files changed
+21409
-1039
No files matched your search
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { sortCharts } from "../../../common/utils";
|
||||
import type { HelmRepo } from "../helm-repo-manager";
|
||||
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
||||
|
||||
const charts = new Map([
|
||||
["stable", {
|
||||
|
||||
@@ -3,27 +3,48 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { helmService } from "../helm-service";
|
||||
import { HelmRepoManager } from "../helm-repo-manager";
|
||||
|
||||
const mockHelmRepoManager = jest.spyOn(HelmRepoManager, "getInstance").mockImplementation();
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import listHelmChartsInjectable from "../helm-service/list-helm-charts.injectable";
|
||||
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";
|
||||
|
||||
jest.mock("../helm-chart-manager");
|
||||
|
||||
describe("Helm Service tests", () => {
|
||||
let listHelmCharts: () => Promise<any>;
|
||||
let getActiveHelmRepositoriesMock: jest.Mock<Promise<AsyncResult<HelmRepo[]>>>;
|
||||
|
||||
beforeEach(() => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
getActiveHelmRepositoriesMock = jest.fn();
|
||||
|
||||
di.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock);
|
||||
|
||||
di.unoverride(listHelmChartsInjectable);
|
||||
di.permitSideEffects(listHelmChartsInjectable);
|
||||
|
||||
listHelmCharts = di.inject(listHelmChartsInjectable);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it("list charts with deprecated entries", async () => {
|
||||
mockHelmRepoManager.mockReturnValue({
|
||||
repositories: jest.fn().mockImplementation(async () => [
|
||||
{ name: "stable", url: "stableurl" },
|
||||
{ name: "experiment", url: "experimenturl" },
|
||||
]),
|
||||
} as any);
|
||||
getActiveHelmRepositoriesMock.mockReturnValue(
|
||||
Promise.resolve({
|
||||
callWasSuccessful: true,
|
||||
|
||||
const charts = await helmService.listCharts();
|
||||
response: [
|
||||
{ name: "stable", url: "stableurl" },
|
||||
{ name: "experiment", url: "experimenturl" },
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
const charts = await listHelmCharts();
|
||||
|
||||
expect(charts).toEqual({
|
||||
stable: {
|
||||
@@ -123,15 +144,14 @@ describe("Helm Service tests", () => {
|
||||
});
|
||||
|
||||
it("list charts sorted by version in descending order", async () => {
|
||||
mockHelmRepoManager.mockReturnValue({
|
||||
repositories: jest.fn().mockImplementation(async () => {
|
||||
return [
|
||||
{ name: "bitnami", url: "bitnamiurl" },
|
||||
];
|
||||
getActiveHelmRepositoriesMock.mockReturnValue(
|
||||
Promise.resolve({
|
||||
callWasSuccessful: true,
|
||||
response: [{ name: "bitnami", url: "bitnamiurl" }],
|
||||
}),
|
||||
} as any);
|
||||
);
|
||||
|
||||
const charts = await helmService.listCharts();
|
||||
const charts = await listHelmCharts();
|
||||
|
||||
expect(charts).toEqual({
|
||||
bitnami: {
|
||||
|
||||
@@ -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 execFileInjectable from "../../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../helm-binary-path.injectable";
|
||||
import type { AsyncResult } from "../../../common/utils/async-result";
|
||||
import { getErrorMessage } from "../../../common/utils/get-error-message";
|
||||
|
||||
const execHelmInjectable = getInjectable({
|
||||
id: "exec-helm",
|
||||
|
||||
instantiate: (di) => {
|
||||
const execFile = di.inject(execFileInjectable);
|
||||
const helmBinaryPath = di.inject(helmBinaryPathInjectable);
|
||||
|
||||
return async (...args: string[]): Promise<AsyncResult<string>> => {
|
||||
try {
|
||||
const response = await execFile(helmBinaryPath, args);
|
||||
|
||||
return { callWasSuccessful: true, response };
|
||||
} catch (error) {
|
||||
return { callWasSuccessful: false, error: getErrorMessage(error) };
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export default execHelmInjectable;
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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 execHelmInjectable from "../exec-helm/exec-helm.injectable";
|
||||
import type { AsyncResult } from "../../../common/utils/async-result";
|
||||
|
||||
export type HelmEnv = Record<string, string> & {
|
||||
HELM_REPOSITORY_CACHE?: string;
|
||||
HELM_REPOSITORY_CONFIG?: string;
|
||||
};
|
||||
|
||||
const getHelmEnvInjectable = getInjectable({
|
||||
id: "get-helm-env",
|
||||
|
||||
instantiate: (di) => {
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
|
||||
return async (): Promise<AsyncResult<HelmEnv>> => {
|
||||
const result = await execHelm("env");
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
return { callWasSuccessful: false, error: result.error };
|
||||
}
|
||||
|
||||
const lines = result.response.split(/\r?\n/); // split by new line feed
|
||||
const env: HelmEnv = {};
|
||||
|
||||
lines.forEach((line: string) => {
|
||||
const [key, value] = line.split("=");
|
||||
|
||||
if (key && value) {
|
||||
env[key] = value.replace(/"/g, ""); // strip quotas
|
||||
}
|
||||
});
|
||||
|
||||
return { callWasSuccessful: true, response: env };
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default getHelmEnvInjectable;
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 { getBinaryName } from "../../common/vars";
|
||||
import getAbsolutePathInjectable from "../../common/path/get-absolute-path.injectable";
|
||||
import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable";
|
||||
import baseBundledBinariesDirectoryInjectable from "../../common/vars/base-bundled-binaries-dir.injectable";
|
||||
|
||||
const helmBinaryPathInjectable = getInjectable({
|
||||
id: "helm-binary-path",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getAbsolutePath = di.inject(getAbsolutePathInjectable);
|
||||
const normalizedPlatform = di.inject(normalizedPlatformInjectable);
|
||||
const baseBundledBinariesDirectory = di.inject(baseBundledBinariesDirectoryInjectable);
|
||||
|
||||
const helmBinaryName = getBinaryName("helm", { forPlatform: normalizedPlatform });
|
||||
|
||||
return getAbsolutePath(baseBundledBinariesDirectory, helmBinaryName);
|
||||
},
|
||||
});
|
||||
|
||||
export default helmBinaryPathInjectable;
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
import fs from "fs";
|
||||
import * as yaml from "js-yaml";
|
||||
import type { HelmRepo } from "./helm-repo-manager";
|
||||
import logger from "../logger";
|
||||
import type { RepoHelmChartList } from "../../common/k8s-api/endpoints/helm-charts.api";
|
||||
import { iter, put, sortCharts } from "../../common/utils";
|
||||
import { execHelm } from "./exec";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import { assert } from "console";
|
||||
import type { HelmRepo } from "../../common/helm/helm-repo";
|
||||
|
||||
interface ChartCacheEntry {
|
||||
data: string; // serialized JSON
|
||||
|
||||
@@ -1,172 +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 yaml from "js-yaml";
|
||||
import { readFile } from "fs-extra";
|
||||
import { customRequestPromise } from "../../common/request";
|
||||
import orderBy from "lodash/orderBy";
|
||||
import logger from "../logger";
|
||||
import { execHelm } from "./exec";
|
||||
import type { HelmEnv, HelmRepo, HelmRepoConfig } from "./helm-repo-manager";
|
||||
|
||||
interface EnsuredHelmRepoManagerData {
|
||||
helmEnv: HelmEnv;
|
||||
didUpdateOnce: boolean;
|
||||
}
|
||||
|
||||
export class HelmRepoManager {
|
||||
protected helmEnv?: HelmEnv;
|
||||
protected didUpdateOnce?: boolean;
|
||||
|
||||
public async loadAvailableRepos(): Promise<HelmRepo[]> {
|
||||
const res = await customRequestPromise({
|
||||
uri: "https://github.com/lensapp/artifact-hub-repositories/releases/download/latest/repositories.json",
|
||||
json: true,
|
||||
resolveWithFullResponse: true,
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
return orderBy(res.body as HelmRepo[], repo => repo.name);
|
||||
}
|
||||
|
||||
private async ensureInitialized(): Promise<EnsuredHelmRepoManagerData> {
|
||||
this.helmEnv ??= await this.parseHelmEnv();
|
||||
|
||||
const repos = await this.list(this.helmEnv);
|
||||
|
||||
if (repos.length === 0) {
|
||||
await this.addRepo({
|
||||
name: "bitnami",
|
||||
url: "https://charts.bitnami.com/bitnami",
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.didUpdateOnce) {
|
||||
await this.update();
|
||||
this.didUpdateOnce = true;
|
||||
}
|
||||
|
||||
return {
|
||||
didUpdateOnce: this.didUpdateOnce,
|
||||
helmEnv: this.helmEnv,
|
||||
};
|
||||
}
|
||||
|
||||
protected async parseHelmEnv() {
|
||||
const output = await execHelm(["env"]);
|
||||
const lines = output.split(/\r?\n/); // split by new line feed
|
||||
const env: Partial<Record<string, string>> = {};
|
||||
|
||||
lines.forEach((line: string) => {
|
||||
const [key, value] = line.split("=");
|
||||
|
||||
if (key && value) {
|
||||
env[key] = value.replace(/"/g, ""); // strip quotas
|
||||
}
|
||||
});
|
||||
|
||||
return env as HelmEnv;
|
||||
}
|
||||
|
||||
public async repo(name: string): Promise<HelmRepo | undefined> {
|
||||
const repos = await this.repositories();
|
||||
|
||||
return repos.find(repo => repo.name === name);
|
||||
}
|
||||
|
||||
private async list(helmEnv: HelmEnv): Promise<HelmRepo[]> {
|
||||
try {
|
||||
const rawConfig = await readFile(helmEnv.HELM_REPOSITORY_CONFIG, "utf8");
|
||||
const parsedConfig = yaml.load(rawConfig) as HelmRepoConfig;
|
||||
|
||||
if (typeof parsedConfig === "object" && parsedConfig) {
|
||||
return parsedConfig.repositories;
|
||||
}
|
||||
} catch {
|
||||
// ignore error
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public async repositories(): Promise<HelmRepo[]> {
|
||||
try {
|
||||
const { helmEnv } = await this.ensureInitialized();
|
||||
|
||||
const repos = await this.list(helmEnv);
|
||||
|
||||
return repos.map(repo => ({
|
||||
...repo,
|
||||
cacheFilePath: `${helmEnv.HELM_REPOSITORY_CACHE}/${repo.name}-index.yaml`,
|
||||
}));
|
||||
} catch (error) {
|
||||
logger.error(`[HELM]: repositories listing error`, error);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async update() {
|
||||
return execHelm([
|
||||
"repo",
|
||||
"update",
|
||||
]);
|
||||
}
|
||||
|
||||
public async addRepo({ name, url, insecureSkipTlsVerify, username, password, caFile, keyFile, certFile }: HelmRepo) {
|
||||
logger.info(`[HELM]: adding repo ${name} from ${url}`);
|
||||
const args = [
|
||||
"repo",
|
||||
"add",
|
||||
name,
|
||||
url,
|
||||
];
|
||||
|
||||
if (insecureSkipTlsVerify) {
|
||||
args.push("--insecure-skip-tls-verify");
|
||||
}
|
||||
|
||||
if (username) {
|
||||
args.push("--username", username);
|
||||
}
|
||||
|
||||
if (password) {
|
||||
args.push("--password", password);
|
||||
}
|
||||
|
||||
if (caFile) {
|
||||
args.push("--ca-file", caFile);
|
||||
}
|
||||
|
||||
if (keyFile) {
|
||||
args.push("--key-file", keyFile);
|
||||
}
|
||||
|
||||
if (certFile) {
|
||||
args.push("--cert-file", certFile);
|
||||
}
|
||||
|
||||
return execHelm(args);
|
||||
}
|
||||
|
||||
public async removeRepo({ name, url }: HelmRepo): Promise<string> {
|
||||
logger.info(`[HELM]: removing repo ${name} (${url})`);
|
||||
|
||||
return execHelm([
|
||||
"repo",
|
||||
"remove",
|
||||
name,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const helmRepoManagerInjectable = getInjectable({
|
||||
id: "helm-repo-manager",
|
||||
|
||||
instantiate: () => new HelmRepoManager(),
|
||||
});
|
||||
|
||||
export default helmRepoManagerInjectable;
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import {
|
||||
asLegacyGlobalSingletonForExtensionApi,
|
||||
} from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-singleton-object-for-extension-api";
|
||||
|
||||
import helmRepoManagerInjectable from "./helm-repo-manager.injectable";
|
||||
|
||||
export type HelmEnv = Partial<Record<string, string>> & {
|
||||
HELM_REPOSITORY_CACHE: string;
|
||||
HELM_REPOSITORY_CONFIG: string;
|
||||
};
|
||||
|
||||
export interface HelmRepoConfig {
|
||||
repositories: HelmRepo[];
|
||||
}
|
||||
|
||||
export interface HelmRepo {
|
||||
name: string;
|
||||
url: string;
|
||||
cacheFilePath?: string;
|
||||
caFile?: string;
|
||||
certFile?: string;
|
||||
insecureSkipTlsVerify?: boolean;
|
||||
keyFile?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export const HelmRepoManager = asLegacyGlobalSingletonForExtensionApi(helmRepoManagerInjectable);
|
||||
@@ -1,134 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { Cluster } from "../../common/cluster/cluster";
|
||||
import logger from "../logger";
|
||||
import { HelmRepoManager } from "./helm-repo-manager";
|
||||
import { HelmChartManager } from "./helm-chart-manager";
|
||||
import { deleteRelease, getHistory, getRelease, getValues, installChart, listReleases, rollback, upgradeRelease } from "./helm-release-manager";
|
||||
import type { JsonObject } from "type-fest";
|
||||
import { object } from "../../common/utils";
|
||||
|
||||
interface GetReleaseValuesArgs {
|
||||
cluster: Cluster;
|
||||
namespace: string;
|
||||
all: boolean;
|
||||
}
|
||||
|
||||
export interface InstallChartArgs {
|
||||
chart: string;
|
||||
values: JsonObject;
|
||||
name: string;
|
||||
namespace: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface UpdateChartArgs {
|
||||
chart: string;
|
||||
values: JsonObject;
|
||||
version: string;
|
||||
}
|
||||
|
||||
class HelmService {
|
||||
public async installChart(cluster: Cluster, data: InstallChartArgs) {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
return installChart(data.chart, data.values, data.name, data.namespace, data.version, proxyKubeconfig);
|
||||
}
|
||||
|
||||
public async listCharts() {
|
||||
const repositories = await HelmRepoManager.getInstance().repositories();
|
||||
|
||||
return object.fromEntries(
|
||||
await Promise.all(repositories.map(async repo => [repo.name, await HelmChartManager.forRepo(repo).charts()] as const)),
|
||||
);
|
||||
}
|
||||
|
||||
public async getChart(repoName: string, chartName: string, version = "") {
|
||||
const repo = await HelmRepoManager.getInstance().repo(repoName);
|
||||
|
||||
if (!repo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const chartManager = HelmChartManager.forRepo(repo);
|
||||
|
||||
return {
|
||||
readme: await chartManager.getReadme(chartName, version),
|
||||
versions: await chartManager.chartVersions(chartName),
|
||||
};
|
||||
}
|
||||
|
||||
public async getChartValues(repoName: string, chartName: string, version = "") {
|
||||
const repo = await HelmRepoManager.getInstance().repo(repoName);
|
||||
|
||||
if (!repo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return HelmChartManager.forRepo(repo).getValues(chartName, version);
|
||||
}
|
||||
|
||||
public async listReleases(cluster: Cluster, namespace?: string) {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("list releases");
|
||||
|
||||
return listReleases(proxyKubeconfig, namespace);
|
||||
}
|
||||
|
||||
public async getRelease(cluster: Cluster, releaseName: string, namespace: string) {
|
||||
const kubeconfigPath = await cluster.getProxyKubeconfigPath();
|
||||
const kubectl = await cluster.ensureKubectl();
|
||||
const kubectlPath = await kubectl.getPath();
|
||||
|
||||
logger.debug("Fetch release");
|
||||
|
||||
return getRelease(releaseName, namespace, kubeconfigPath, kubectlPath);
|
||||
}
|
||||
|
||||
public async getReleaseValues(releaseName: string, { cluster, namespace, all }: GetReleaseValuesArgs) {
|
||||
const pathToKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Fetch release values");
|
||||
|
||||
return getValues(releaseName, { namespace, all, kubeconfigPath: pathToKubeconfig });
|
||||
}
|
||||
|
||||
public async getReleaseHistory(cluster: Cluster, releaseName: string, namespace: string) {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Fetch release history");
|
||||
|
||||
return getHistory(releaseName, namespace, proxyKubeconfig);
|
||||
}
|
||||
|
||||
public async deleteRelease(cluster: Cluster, releaseName: string, namespace: string) {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Delete release");
|
||||
|
||||
return deleteRelease(releaseName, namespace, proxyKubeconfig);
|
||||
}
|
||||
|
||||
public async updateRelease(cluster: Cluster, releaseName: string, namespace: string, data: UpdateChartArgs) {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
const kubectl = await cluster.ensureKubectl();
|
||||
const kubectlPath = await kubectl.getPath();
|
||||
|
||||
logger.debug("Upgrade release");
|
||||
|
||||
return upgradeRelease(releaseName, data.chart, data.values, namespace, data.version, proxyKubeconfig, kubectlPath);
|
||||
}
|
||||
|
||||
public async rollback(cluster: Cluster, releaseName: string, namespace: string, revision: number) {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Rollback release");
|
||||
await rollback(releaseName, namespace, revision, proxyKubeconfig);
|
||||
}
|
||||
}
|
||||
|
||||
export const helmService = new HelmService();
|
||||
@@ -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 type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { deleteRelease } from "../helm-release-manager";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
const deleteHelmReleaseInjectable = getInjectable({
|
||||
id: "delete-helm-release",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (cluster: Cluster, releaseName: string, namespace: string) => {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Delete release");
|
||||
|
||||
return deleteRelease(releaseName, namespace, proxyKubeconfig);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default deleteHelmReleaseInjectable;
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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 { HelmChartManager } from "../helm-chart-manager";
|
||||
import getActiveHelmRepositoryInjectable from "../repositories/get-active-helm-repository.injectable";
|
||||
|
||||
const getHelmChartValuesInjectable = getInjectable({
|
||||
id: "get-helm-chart-values",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getActiveHelmRepository = di.inject(getActiveHelmRepositoryInjectable);
|
||||
|
||||
return async (repoName: string, chartName: string, version = "") => {
|
||||
const repo = await getActiveHelmRepository(repoName);
|
||||
|
||||
if (!repo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return HelmChartManager.forRepo(repo).getValues(chartName, version);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default getHelmChartValuesInjectable;
|
||||
@@ -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 { HelmChartManager } from "../helm-chart-manager";
|
||||
import getActiveHelmRepositoryInjectable from "../repositories/get-active-helm-repository.injectable";
|
||||
|
||||
const getHelmChartInjectable = getInjectable({
|
||||
id: "get-helm-chart",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getActiveHelmRepository = di.inject(getActiveHelmRepositoryInjectable);
|
||||
|
||||
return async (repoName: string, chartName: string, version = "") => {
|
||||
const repo = await getActiveHelmRepository(repoName);
|
||||
|
||||
if (!repo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const chartManager = HelmChartManager.forRepo(repo);
|
||||
|
||||
return {
|
||||
readme: await chartManager.getReadme(chartName, version),
|
||||
versions: await chartManager.chartVersions(chartName),
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default getHelmChartInjectable;
|
||||
@@ -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 type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { getHistory } from "../helm-release-manager";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
const getHelmReleaseHistoryInjectable = getInjectable({
|
||||
id: "get-helm-release-history",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (cluster: Cluster, releaseName: string, namespace: string) => {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Fetch release history");
|
||||
|
||||
return getHistory(releaseName, namespace, proxyKubeconfig);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default getHelmReleaseHistoryInjectable;
|
||||
@@ -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 { getValues } from "../helm-release-manager";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { Cluster } from "../../../common/cluster/cluster";
|
||||
|
||||
interface GetReleaseValuesArgs {
|
||||
cluster: Cluster;
|
||||
namespace: string;
|
||||
all: boolean;
|
||||
}
|
||||
|
||||
const getHelmReleaseValuesInjectable = getInjectable({
|
||||
id: "get-helm-release-values",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (
|
||||
releaseName: string,
|
||||
{ cluster, namespace, all }: GetReleaseValuesArgs,
|
||||
) => {
|
||||
const pathToKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Fetch release values");
|
||||
|
||||
return getValues(releaseName, {
|
||||
namespace,
|
||||
all,
|
||||
kubeconfigPath: pathToKubeconfig,
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default getHelmReleaseValuesInjectable;
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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 { Cluster } from "../../../common/cluster/cluster";
|
||||
import { getRelease } from "../helm-release-manager";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
const getHelmReleaseInjectable = getInjectable({
|
||||
id: "get-helm-release",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (cluster: Cluster, releaseName: string, namespace: string) => {
|
||||
const kubeconfigPath = await cluster.getProxyKubeconfigPath();
|
||||
const kubectl = await cluster.ensureKubectl();
|
||||
const kubectlPath = await kubectl.getPath();
|
||||
|
||||
logger.debug("Fetch release");
|
||||
|
||||
return getRelease(releaseName, namespace, kubeconfigPath, kubectlPath);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default getHelmReleaseInjectable;
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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 { JsonObject } from "type-fest";
|
||||
import type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { installChart } from "../helm-release-manager";
|
||||
|
||||
export interface InstallChartArgs {
|
||||
chart: string;
|
||||
values: JsonObject;
|
||||
name: string;
|
||||
namespace: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
const installHelmChartInjectable = getInjectable({
|
||||
id: "install-helm-chart",
|
||||
|
||||
instantiate: () => async (cluster: Cluster, data: InstallChartArgs) => {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
return installChart(data.chart, data.values, data.name, data.namespace, data.version, proxyKubeconfig);
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default installHelmChartInjectable;
|
||||
@@ -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 assert from "assert";
|
||||
import { object } from "../../../common/utils";
|
||||
import { HelmChartManager } from "../helm-chart-manager";
|
||||
import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
|
||||
const listHelmChartsInjectable = getInjectable({
|
||||
id: "list-helm-charts",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
|
||||
|
||||
return async () => {
|
||||
const result = await getActiveHelmRepositories();
|
||||
|
||||
assert(result.callWasSuccessful);
|
||||
|
||||
const repositories = result.response;
|
||||
|
||||
return object.fromEntries(
|
||||
await Promise.all(
|
||||
repositories.map(
|
||||
async (repo) =>
|
||||
[
|
||||
repo.name,
|
||||
await HelmChartManager.forRepo(repo).charts(),
|
||||
] as const,
|
||||
),
|
||||
),
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default listHelmChartsInjectable;
|
||||
@@ -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 type { Cluster } from "../../../common/cluster/cluster";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import { listReleases } from "../helm-release-manager";
|
||||
|
||||
const listHelmReleasesInjectable = getInjectable({
|
||||
id: "list-helm-releases",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (cluster: Cluster, namespace?: string) => {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("list releases");
|
||||
|
||||
return listReleases(proxyKubeconfig, namespace);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default listHelmReleasesInjectable;
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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 { Cluster } from "../../../common/cluster/cluster";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import { rollback } from "../helm-release-manager";
|
||||
|
||||
const rollbackHelmReleaseInjectable = getInjectable({
|
||||
id: "rollback-helm-release",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (
|
||||
cluster: Cluster,
|
||||
releaseName: string,
|
||||
namespace: string,
|
||||
revision: number,
|
||||
) => {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
|
||||
logger.debug("Rollback release");
|
||||
await rollback(releaseName, namespace, revision, proxyKubeconfig);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default rollbackHelmReleaseInjectable;
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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 { Cluster } from "../../../common/cluster/cluster";
|
||||
import { upgradeRelease } from "../helm-release-manager";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { JsonObject } from "type-fest";
|
||||
|
||||
export interface UpdateChartArgs {
|
||||
chart: string;
|
||||
values: JsonObject;
|
||||
version: string;
|
||||
}
|
||||
|
||||
const updateHelmReleaseInjectable = getInjectable({
|
||||
id: "update-helm-release",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (cluster: Cluster, releaseName: string, namespace: string, data: UpdateChartArgs) => {
|
||||
const proxyKubeconfig = await cluster.getProxyKubeconfigPath();
|
||||
const kubectl = await cluster.ensureKubectl();
|
||||
const kubectlPath = await kubectl.getPath();
|
||||
|
||||
logger.debug("Upgrade release");
|
||||
|
||||
return upgradeRelease(
|
||||
releaseName,
|
||||
data.chart,
|
||||
data.values,
|
||||
namespace,
|
||||
data.version,
|
||||
proxyKubeconfig,
|
||||
kubectlPath,
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default updateHelmReleaseInjectable;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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 addHelmRepositoryChannelInjectable from "../../../../common/helm/add-helm-repository-channel.injectable";
|
||||
import addHelmRepositoryInjectable from "./add-helm-repository.injectable";
|
||||
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
const addHelmRepositoryChannelListenerInjectable = getInjectable({
|
||||
id: "add-helm-repository-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const addHelmRepository = di.inject(addHelmRepositoryInjectable);
|
||||
const channel = di.inject(addHelmRepositoryChannelInjectable);
|
||||
|
||||
return {
|
||||
channel,
|
||||
handler: addHelmRepository,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default addHelmRepositoryChannelListenerInjectable;
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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 execHelmInjectable from "../../exec-helm/exec-helm.injectable";
|
||||
import type { HelmRepo } from "../../../../common/helm/helm-repo";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
|
||||
const addHelmRepositoryInjectable = getInjectable({
|
||||
id: "add-helm-repository",
|
||||
|
||||
instantiate: (di) => {
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (repo: HelmRepo) => {
|
||||
const {
|
||||
name,
|
||||
url,
|
||||
insecureSkipTlsVerify,
|
||||
username,
|
||||
password,
|
||||
caFile,
|
||||
keyFile,
|
||||
certFile,
|
||||
} = repo;
|
||||
|
||||
logger.info(`[HELM]: adding repo ${name} from ${url}`);
|
||||
|
||||
const args = ["repo", "add", name, url];
|
||||
|
||||
if (insecureSkipTlsVerify) {
|
||||
args.push("--insecure-skip-tls-verify");
|
||||
}
|
||||
|
||||
if (username) {
|
||||
args.push("--username", username);
|
||||
}
|
||||
|
||||
if (password) {
|
||||
args.push("--password", password);
|
||||
}
|
||||
|
||||
if (caFile) {
|
||||
args.push("--ca-file", caFile);
|
||||
}
|
||||
|
||||
if (keyFile) {
|
||||
args.push("--key-file", keyFile);
|
||||
}
|
||||
|
||||
if (certFile) {
|
||||
args.push("--cert-file", certFile);
|
||||
}
|
||||
|
||||
return await execHelm(...args);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default addHelmRepositoryInjectable;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import getActiveHelmRepositoriesChannelInjectable from "../../../../common/helm/get-active-helm-repositories-channel.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable";
|
||||
|
||||
const getActiveHelmRepositoriesChannelListenerInjectable = getInjectable({
|
||||
id: "get-active-helm-repositories-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
|
||||
|
||||
return {
|
||||
channel: di.inject(getActiveHelmRepositoriesChannelInjectable),
|
||||
|
||||
handler: getActiveHelmRepositories,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default getActiveHelmRepositoriesChannelListenerInjectable;
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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 { HelmRepo } from "../../../../common/helm/helm-repo";
|
||||
import type { ReadYamlFile } from "../../../../common/fs/read-yaml-file.injectable";
|
||||
import readYamlFileInjectable from "../../../../common/fs/read-yaml-file.injectable";
|
||||
import getHelmEnvInjectable from "../../get-helm-env/get-helm-env.injectable";
|
||||
import execHelmInjectable from "../../exec-helm/exec-helm.injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import type { AsyncResult } from "../../../../common/utils/async-result";
|
||||
|
||||
interface HelmRepositoryFromYaml {
|
||||
name: string;
|
||||
url: string;
|
||||
caFile: string;
|
||||
certFile: string;
|
||||
insecure_skip_tls_verify: boolean;
|
||||
keyFile: string;
|
||||
pass_credentials_all: boolean;
|
||||
password: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface HelmRepositoriesFromYaml {
|
||||
repositories: HelmRepositoryFromYaml[];
|
||||
}
|
||||
|
||||
const getActiveHelmRepositoriesInjectable = getInjectable({
|
||||
id: "get-helm-repositories",
|
||||
|
||||
instantiate: (di) => {
|
||||
const readYamlFile = di.inject(readYamlFileInjectable);
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
const getHelmEnv = di.inject(getHelmEnvInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
const getRepositories = getRepositoriesFor(readYamlFile);
|
||||
|
||||
return async (): Promise<AsyncResult<HelmRepo[]>> => {
|
||||
const envResult = await getHelmEnv();
|
||||
|
||||
if (!envResult.callWasSuccessful) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Error getting Helm configuration: ${envResult.error}`,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
HELM_REPOSITORY_CONFIG: repositoryConfigFilePath,
|
||||
HELM_REPOSITORY_CACHE: helmRepositoryCacheDirPath,
|
||||
} = envResult.response;
|
||||
|
||||
if (!repositoryConfigFilePath) {
|
||||
const errorMessage = "Tried to get Helm repositories, but HELM_REPOSITORY_CONFIG was not present in `$ helm env`.";
|
||||
|
||||
logger.error(errorMessage);
|
||||
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Error getting Helm configuration: ${errorMessage}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (!helmRepositoryCacheDirPath) {
|
||||
const errorMessage = "Tried to get Helm repositories, but HELM_REPOSITORY_CACHE was not present in `$ helm env`.";
|
||||
|
||||
logger.error(errorMessage);
|
||||
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Error getting Helm configuration: ${errorMessage}`,
|
||||
};
|
||||
}
|
||||
|
||||
const updateResult = await execHelm("repo", "update");
|
||||
|
||||
if (!updateResult.callWasSuccessful) {
|
||||
if (!updateResult.error.includes(internalHelmErrorForNoRepositoriesFound)) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Error updating Helm repositories: ${updateResult.error}`,
|
||||
};
|
||||
}
|
||||
const resultOfAddingDefaultRepository = await execHelm("repo", "add", "bitnami", "https://charts.bitnami.com/bitnami");
|
||||
|
||||
if (!resultOfAddingDefaultRepository.callWasSuccessful) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: `Error when adding default Helm repository: ${resultOfAddingDefaultRepository.error}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
|
||||
response: await getRepositories(
|
||||
repositoryConfigFilePath,
|
||||
helmRepositoryCacheDirPath,
|
||||
),
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default getActiveHelmRepositoriesInjectable;
|
||||
|
||||
const getRepositoriesFor =
|
||||
(readYamlFile: ReadYamlFile) =>
|
||||
async (repositoryConfigFilePath: string, helmRepositoryCacheDirPath: string): Promise<HelmRepo[]> => {
|
||||
const { repositories } = (await readYamlFile(
|
||||
repositoryConfigFilePath,
|
||||
)) as HelmRepositoriesFromYaml;
|
||||
|
||||
return repositories.map((repository) => ({
|
||||
name: repository.name,
|
||||
url: repository.url,
|
||||
caFile: repository.caFile,
|
||||
certFile: repository.certFile,
|
||||
insecureSkipTlsVerify: repository.insecure_skip_tls_verify,
|
||||
keyFile: repository.keyFile,
|
||||
username: repository.username,
|
||||
password: repository.password,
|
||||
cacheFilePath: `${helmRepositoryCacheDirPath}/${repository.name}-index.yaml`,
|
||||
}));
|
||||
};
|
||||
|
||||
const internalHelmErrorForNoRepositoriesFound = "no repositories found. You must add one before updating";
|
||||
@@ -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 assert from "assert";
|
||||
import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
|
||||
const getActiveHelmRepositoryInjectable = getInjectable({
|
||||
id: "get-active-helm-repository",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
|
||||
|
||||
return async (name: string) => {
|
||||
const activeHelmRepositories = await getActiveHelmRepositories();
|
||||
|
||||
assert(activeHelmRepositories.callWasSuccessful);
|
||||
|
||||
return activeHelmRepositories.response.find(
|
||||
(repository) => repository.name === name,
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default getActiveHelmRepositoryInjectable;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable";
|
||||
import removeHelmRepositoryChannelInjectable from "../../../../common/helm/remove-helm-repository-channel.injectable";
|
||||
|
||||
const removeHelmRepositoryChannelListenerInjectable = getInjectable({
|
||||
id: "remove-helm-repository-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const removeHelmRepository = di.inject(removeHelmRepositoryInjectable);
|
||||
const channel = di.inject(removeHelmRepositoryChannelInjectable);
|
||||
|
||||
return {
|
||||
channel,
|
||||
handler: removeHelmRepository,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default removeHelmRepositoryChannelListenerInjectable;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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 execHelmInjectable from "../../exec-helm/exec-helm.injectable";
|
||||
import type { HelmRepo } from "../../../../common/helm/helm-repo";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
|
||||
const removeHelmRepositoryInjectable = getInjectable({
|
||||
id: "remove-helm-repository",
|
||||
|
||||
instantiate: (di) => {
|
||||
const execHelm = di.inject(execHelmInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (repo: HelmRepo) => {
|
||||
logger.info(`[HELM]: removing repo ${repo.name} (${repo.url})`);
|
||||
|
||||
return execHelm(
|
||||
"repo",
|
||||
"remove",
|
||||
repo.name,
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default removeHelmRepositoryInjectable;
|
||||
Reference in new issue
Block a user