UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

195 lines 9.43 kB
// SPDX-License-Identifier: Apache-2.0 var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; import * as constants from './constants.js'; import chalk from 'chalk'; import { SoloError } from './errors/solo-error.js'; import { inject, injectable } from 'tsyringe-neo'; import { patchInject } from './dependency-injection/container-helper.js'; import { InjectTokens } from './dependency-injection/inject-tokens.js'; import { Repository } from '../integration/helm/model/repository.js'; import { UpgradeChartOptions } from '../integration/helm/model/upgrade/upgrade-chart-options.js'; import { Chart } from '../integration/helm/model/chart.js'; import { InstallChartOptionsBuilder } from '../integration/helm/model/install/install-chart-options-builder.js'; import { UnInstallChartOptionsBuilder } from '../integration/helm/model/install/un-install-chart-options-builder.js'; import { AddRepoOptionsBuilder } from '../integration/helm/model/add/add-repo-options-builder.js'; let ChartManager = class ChartManager { helm; logger; constructor(helm, logger) { this.helm = helm; this.logger = logger; this.helm = patchInject(helm, InjectTokens.Helm, this.constructor.name); this.logger = patchInject(logger, InjectTokens.SoloLogger, this.constructor.name); } /** * Setup chart repositories * * This must be invoked before calling other methods * * @param repoURLs - a map of name and chart repository URLs * @param force - whether or not to update the repo * @returns the urls */ async setup(repoURLs = constants.DEFAULT_CHART_REPO, force = true) { try { const promises = []; for (const [name, url] of repoURLs.entries()) { this.logger.debug(`pushing promise for: add repo ${name} -> ${url}`); promises.push(this.addRepo(name, url, force)); } const urls = await Promise.all(promises); // urls await this.helm.updateRepositories(); return urls; } catch (error) { throw new SoloError(`failed to setup chart repositories: ${error.message}`, error); } } /** * Check if the required chart repositories are set up * * @param repoURLs - a map of name and chart repository URLs * @returns true if all repos are set up, false otherwise */ async isSetup(repoURLs = constants.DEFAULT_CHART_REPO) { try { const existingRepos = await this.helm.listRepositories(); for (const [name, url] of repoURLs.entries()) { const found = existingRepos.find((repo) => repo.name === name && repo.url === url); if (!found) { this.logger.debug(`Repo not found: ${name} -> ${url}`); return false; } } return true; } catch (error) { throw new SoloError(`failed to check chart repositories: ${error.message}`, error); } } async addRepo(name, url, force) { // detect if repo already exists for name provided and the url matches, if so, exit, otherwise force update const repositories = await this.helm.listRepositories(); const existingRepo = repositories.find((repo) => repo.name === name); if (existingRepo) { if (existingRepo.url === url) { this.logger.debug(`Repo already exists: ${name} -> ${url}`); return url; } this.logger.debug(`Repo URL mismatch for ${name}: existing URL is ${existingRepo.url}, new URL is ${url}`); } this.logger.debug(`Adding repo ${name} -> ${url}`, { repoName: name, repoURL: url }); const options = new AddRepoOptionsBuilder().forceUpdate(force).build(); await this.helm.addRepository(new Repository(name, url), options); return url; } /** List available clusters * * @param namespaceName - the namespace name * @param kubeContext - the kube context */ async getInstalledCharts(namespaceName, kubeContext) { try { const result = await this.helm.listReleases(!namespaceName, namespaceName?.name, kubeContext); // convert to string[] return result.map((release) => `${release.name} [${release.chart}]`); } catch (error) { this.logger.showUserError(error); throw new SoloError(`failed to list installed charts: ${error.message}`, error); } } async install(namespaceName, chartReleaseName, chartName, repoName, version, valuesArgument = '', kubeContext, atomic = false, waitFor = false) { try { const isInstalled = await this.isChartInstalled(namespaceName, chartReleaseName, kubeContext); if (isInstalled) { this.logger.debug(`OK: chart is already installed:${chartReleaseName} (${chartName}) (${repoName})`); } else { this.logger.debug(`> installing chart:${chartName}`); const builder = InstallChartOptionsBuilder.builder() .version(version) .kubeContext(kubeContext) .atomic(atomic) .waitFor(waitFor) .extraArgs(valuesArgument); if (namespaceName) { builder.createNamespace(true); builder.namespace(namespaceName.name); } const options = builder.build(); await this.helm.installChart(chartReleaseName, new Chart(chartName, repoName), options); this.logger.debug(`OK: chart is installed: ${chartReleaseName} (${chartName}) (${repoName})`); } } catch (error) { throw new SoloError(`failed to install chart ${chartReleaseName}: ${error.message}`, error); } return true; } async isChartInstalled(namespaceName, chartReleaseName, kubeContext) { this.logger.debug(`> checking if chart is installed [ chart: ${chartReleaseName}, namespace: ${namespaceName}, kubeContext: ${kubeContext} ]`); const charts = await this.getInstalledCharts(namespaceName, kubeContext); let match = false; for (const chart of charts) { if (chart.split(' ')[0] === chartReleaseName) { match = true; break; } } return match; } async uninstall(namespaceName, chartReleaseName, kubeContext) { try { const isInstalled = await this.isChartInstalled(namespaceName, chartReleaseName, kubeContext); if (isInstalled) { this.logger.debug(`uninstalling chart release: ${chartReleaseName}`); const options = UnInstallChartOptionsBuilder.builder() .namespace(namespaceName.name) .kubeContext(kubeContext) .build(); await this.helm.uninstallChart(chartReleaseName, options); this.logger.debug(`OK: chart release is uninstalled: ${chartReleaseName}`); } else { this.logger.debug(`OK: chart release is already uninstalled: ${chartReleaseName}`); } } catch (error) { throw new SoloError(`failed to uninstall chart ${chartReleaseName}: ${error.message}`, error); } return true; } async upgrade(namespaceName, chartReleaseName, chartName, repoName, version = '', valuesArgument = '', kubeContext, reuseValues) { try { this.logger.debug(chalk.cyan('> upgrading chart:'), chalk.yellow(`${chartReleaseName}`)); const options = new UpgradeChartOptions(namespaceName?.name, kubeContext, reuseValues ?? true, valuesArgument, version); const chart = new Chart(chartName, repoName); await this.helm.upgradeChart(chartReleaseName, chart, options); this.logger.debug(chalk.green('OK'), `chart '${chartReleaseName}' is upgraded`); } catch (error) { throw new SoloError(`failed to upgrade chart ${chartReleaseName}: ${error.message}`, error); } return true; } }; ChartManager = __decorate([ injectable(), __param(0, inject(InjectTokens.Helm)), __param(1, inject(InjectTokens.SoloLogger)), __metadata("design:paramtypes", [Object, Object]) ], ChartManager); export { ChartManager }; //# sourceMappingURL=chart-manager.js.map