@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
317 lines • 14.7 kB
JavaScript
/**
* SPDX-License-Identifier: Apache-2.0
*/
import { FREEZE_ADMIN_ACCOUNT } from '../../core/constants.js';
import { Templates } from '../../core/templates.js';
import * as constants from '../../core/constants.js';
import { PrivateKey } from '@hashgraph/sdk';
import { SoloError } from '../../core/errors.js';
import * as helpers from '../../core/helpers.js';
import path from 'path';
import fs from 'fs';
import { validatePath } from '../../core/helpers.js';
import { resolveNamespaceFromDeployment } from '../../core/resolvers.js';
import { Flags as flags } from '../flags.js';
export const PREPARE_UPGRADE_CONFIGS_NAME = 'prepareUpgradeConfig';
export const DOWNLOAD_GENERATED_FILES_CONFIGS_NAME = 'downloadGeneratedFilesConfig';
export const ADD_CONFIGS_NAME = 'addConfigs';
export const DELETE_CONFIGS_NAME = 'deleteConfigs';
export const UPDATE_CONFIGS_NAME = 'updateConfigs';
export const UPGRADE_CONFIGS_NAME = 'upgradeConfigs';
export const REFRESH_CONFIGS_NAME = 'refreshConfigs';
export const KEYS_CONFIGS_NAME = 'keyConfigs';
export const SETUP_CONFIGS_NAME = 'setupConfigs';
export const START_CONFIGS_NAME = 'startConfigs';
const initializeSetup = async (config, k8Factory) => {
// compute other config parameters
config.keysDir = path.join(validatePath(config.cacheDir), 'keys');
config.stagingDir = Templates.renderStagingDir(config.cacheDir, config.releaseTag);
config.stagingKeysDir = path.join(validatePath(config.stagingDir), 'keys');
if (!(await k8Factory.default().namespaces().has(config.namespace))) {
throw new SoloError(`namespace ${config.namespace} does not exist`);
}
// prepare staging keys directory
if (!fs.existsSync(config.stagingKeysDir)) {
fs.mkdirSync(config.stagingKeysDir, { recursive: true });
}
// create cached keys dir if it does not exist yet
if (!fs.existsSync(config.keysDir)) {
fs.mkdirSync(config.keysDir);
}
};
export const prepareUpgradeConfigBuilder = async function (argv, ctx, task) {
const config = this.getConfig(PREPARE_UPGRADE_CONFIGS_NAME, argv.flags, [
'nodeClient',
'freezeAdminPrivateKey',
'namespace',
'consensusNodes',
'contexts',
]);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
await initializeSetup(config, this.k8Factory);
config.nodeClient = await this.accountManager.loadNodeClient(config.namespace, this.parent.getClusterRefs(), config.deployment);
const accountKeys = await this.accountManager.getAccountKeysFromSecret(FREEZE_ADMIN_ACCOUNT, config.namespace);
config.freezeAdminPrivateKey = accountKeys.privateKey;
return config;
};
export const downloadGeneratedFilesConfigBuilder = async function (argv, ctx, task) {
const config = this.getConfig(DOWNLOAD_GENERATED_FILES_CONFIGS_NAME, argv.flags, [
'allNodeAliases',
'existingNodeAliases',
'serviceMap',
'namespace',
'consensusNodes',
'contexts',
]);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
config.existingNodeAliases = [];
await initializeSetup(config, this.k8Factory);
return config;
};
export const upgradeConfigBuilder = async function (argv, ctx, task, shouldLoadNodeClient = true) {
const config = this.getConfig(UPGRADE_CONFIGS_NAME, argv.flags, [
'allNodeAliases',
'existingNodeAliases',
'keysDir',
'nodeClient',
'podRefs',
'stagingDir',
'stagingKeysDir',
'namespace',
'consensusNodes',
'contexts',
]);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
config.curDate = new Date();
config.existingNodeAliases = [];
config.nodeAliases = helpers.parseNodeAliases(config.nodeAliasesUnparsed);
await initializeSetup(config, this.k8Factory);
// set config in the context for later tasks to use
ctx.config = config;
ctx.config.chartPath = await this.prepareChartPath(ctx.config.chartDirectory, constants.SOLO_TESTING_CHART_URL, constants.SOLO_DEPLOYMENT_CHART);
if (shouldLoadNodeClient) {
ctx.config.nodeClient = await this.accountManager.loadNodeClient(ctx.config.namespace, this.parent.getClusterRefs(), config.deployment);
}
const accountKeys = await this.accountManager.getAccountKeysFromSecret(FREEZE_ADMIN_ACCOUNT, config.namespace);
config.freezeAdminPrivateKey = accountKeys.privateKey;
return config;
};
export const updateConfigBuilder = async function (argv, ctx, task, shouldLoadNodeClient = true) {
const config = this.getConfig(UPDATE_CONFIGS_NAME, argv.flags, [
'allNodeAliases',
'existingNodeAliases',
'freezeAdminPrivateKey',
'keysDir',
'nodeClient',
'podRefs',
'serviceMap',
'stagingDir',
'stagingKeysDir',
'treasuryKey',
'namespace',
'consensusNodes',
'contexts',
]);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
config.curDate = new Date();
config.existingNodeAliases = [];
await initializeSetup(config, this.k8Factory);
// set config in the context for later tasks to use
ctx.config = config;
ctx.config.chartPath = await this.prepareChartPath(ctx.config.chartDirectory, constants.SOLO_TESTING_CHART_URL, constants.SOLO_DEPLOYMENT_CHART);
if (shouldLoadNodeClient) {
ctx.config.nodeClient = await this.accountManager.loadNodeClient(ctx.config.namespace, this.parent.getClusterRefs(), config.deployment);
}
const accountKeys = await this.accountManager.getAccountKeysFromSecret(FREEZE_ADMIN_ACCOUNT, config.namespace);
config.freezeAdminPrivateKey = accountKeys.privateKey;
const treasuryAccount = await this.accountManager.getTreasuryAccountKeys(config.namespace);
const treasuryAccountPrivateKey = treasuryAccount.privateKey;
config.treasuryKey = PrivateKey.fromStringED25519(treasuryAccountPrivateKey);
return config;
};
export const deleteConfigBuilder = async function (argv, ctx, task, shouldLoadNodeClient = true) {
const config = this.getConfig(DELETE_CONFIGS_NAME, argv.flags, [
'adminKey',
'allNodeAliases',
'existingNodeAliases',
'freezeAdminPrivateKey',
'keysDir',
'nodeClient',
'podRefs',
'serviceMap',
'stagingDir',
'stagingKeysDir',
'treasuryKey',
'namespace',
'consensusNodes',
'contexts',
]);
config.curDate = new Date();
config.existingNodeAliases = [];
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
await initializeSetup(config, this.k8Factory);
// set config in the context for later tasks to use
ctx.config = config;
ctx.config.chartPath = await this.prepareChartPath(ctx.config.chartDirectory, constants.SOLO_TESTING_CHART_URL, constants.SOLO_DEPLOYMENT_CHART);
if (shouldLoadNodeClient) {
ctx.config.nodeClient = await this.accountManager.loadNodeClient(ctx.config.namespace, this.parent.getClusterRefs(), config.deployment);
}
const accountKeys = await this.accountManager.getAccountKeysFromSecret(FREEZE_ADMIN_ACCOUNT, config.namespace);
config.freezeAdminPrivateKey = accountKeys.privateKey;
const treasuryAccount = await this.accountManager.getTreasuryAccountKeys(config.namespace);
const treasuryAccountPrivateKey = treasuryAccount.privateKey;
config.treasuryKey = PrivateKey.fromStringED25519(treasuryAccountPrivateKey);
return config;
};
export const addConfigBuilder = async function (argv, ctx, task, shouldLoadNodeClient = true) {
const config = this.getConfig(ADD_CONFIGS_NAME, argv.flags, [
'allNodeAliases',
'chartPath',
'curDate',
'existingNodeAliases',
'freezeAdminPrivateKey',
'keysDir',
'lastStateZipPath',
'nodeClient',
'podRefs',
'serviceMap',
'stagingDir',
'stagingKeysDir',
'treasuryKey',
'namespace',
'consensusNodes',
'contexts',
]);
ctx.adminKey = argv[flags.adminKey.name]
? PrivateKey.fromStringED25519(argv[flags.adminKey.name])
: PrivateKey.fromStringED25519(constants.GENESIS_KEY);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
config.curDate = new Date();
config.existingNodeAliases = [];
await initializeSetup(config, this.k8Factory);
// set config in the context for later tasks to use
ctx.config = config;
ctx.config.chartPath = await this.prepareChartPath(ctx.config.chartDirectory, constants.SOLO_TESTING_CHART_URL, constants.SOLO_DEPLOYMENT_CHART);
if (shouldLoadNodeClient) {
ctx.config.nodeClient = await this.accountManager.loadNodeClient(ctx.config.namespace, this.parent.getClusterRefs(), config.deployment);
}
const accountKeys = await this.accountManager.getAccountKeysFromSecret(FREEZE_ADMIN_ACCOUNT, config.namespace);
config.freezeAdminPrivateKey = accountKeys.privateKey;
const treasuryAccount = await this.accountManager.getTreasuryAccountKeys(config.namespace);
const treasuryAccountPrivateKey = treasuryAccount.privateKey;
config.treasuryKey = PrivateKey.fromStringED25519(treasuryAccountPrivateKey);
config.serviceMap = await this.accountManager.getNodeServiceMap(config.namespace, this.parent.getClusterRefs(), config.deployment);
config.consensusNodes = this.parent.getConsensusNodes();
config.contexts = this.parent.getContexts();
return config;
};
export const logsConfigBuilder = async function (argv, ctx, task) {
const config = {
namespace: await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task),
nodeAliases: helpers.parseNodeAliases(this.configManager.getFlag(flags.nodeAliasesUnparsed)),
nodeAliasesUnparsed: this.configManager.getFlag(flags.nodeAliasesUnparsed),
deployment: this.configManager.getFlag(flags.deployment),
consensusNodes: this.parent.getConsensusNodes(),
contexts: this.parent.getContexts(),
};
ctx.config = config;
return config;
};
export const statesConfigBuilder = async function (argv, ctx, task) {
const config = {
namespace: await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task),
nodeAliases: helpers.parseNodeAliases(this.configManager.getFlag(flags.nodeAliasesUnparsed)),
nodeAliasesUnparsed: this.configManager.getFlag(flags.nodeAliasesUnparsed),
deployment: this.configManager.getFlag(flags.deployment),
consensusNodes: this.parent.getConsensusNodes(),
contexts: this.parent.getContexts(),
};
ctx.config = config;
return config;
};
export const refreshConfigBuilder = async function (argv, ctx, task) {
ctx.config = this.getConfig(REFRESH_CONFIGS_NAME, argv.flags, [
'nodeAliases',
'podRefs',
'namespace',
'consensusNodes',
'contexts',
]);
ctx.config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
ctx.config.nodeAliases = helpers.parseNodeAliases(ctx.config.nodeAliasesUnparsed);
await initializeSetup(ctx.config, this.k8Factory);
return ctx.config;
};
export const keysConfigBuilder = function (argv, ctx, task) {
const config = this.getConfig(KEYS_CONFIGS_NAME, argv.flags, [
'curDate',
'keysDir',
'nodeAliases',
'consensusNodes',
'contexts',
]);
config.curDate = new Date();
config.nodeAliases = helpers.parseNodeAliases(config.nodeAliasesUnparsed);
if (config.nodeAliases.length === 0) {
config.nodeAliases = this.consensusNodes.map((node) => {
return node.name;
});
if (config.nodeAliases.length === 0) {
throw new SoloError('no node aliases provided via flags or RemoteConfig');
}
}
config.keysDir = path.join(this.configManager.getFlag(flags.cacheDir), 'keys');
if (!fs.existsSync(config.keysDir)) {
fs.mkdirSync(config.keysDir);
}
return config;
};
export const stopConfigBuilder = async function (argv, ctx, task) {
ctx.config = {
namespace: await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task),
nodeAliases: helpers.parseNodeAliases(this.configManager.getFlag(flags.nodeAliasesUnparsed)),
nodeAliasesUnparsed: this.configManager.getFlag(flags.nodeAliasesUnparsed),
deployment: this.configManager.getFlag(flags.deployment),
consensusNodes: this.parent.getConsensusNodes(),
contexts: this.parent.getContexts(),
};
if (!(await this.k8Factory.default().namespaces().has(ctx.config.namespace))) {
throw new SoloError(`namespace ${ctx.config.namespace} does not exist`);
}
return ctx.config;
};
export const startConfigBuilder = async function (argv, ctx, task) {
const config = this.getConfig(START_CONFIGS_NAME, argv.flags, [
'nodeAliases',
'namespace',
'consensusNodes',
'contexts',
]);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
config.consensusNodes = this.parent.getConsensusNodes();
for (const consensusNode of config.consensusNodes) {
const k8 = this.k8Factory.getK8(consensusNode.context);
if (!(await k8.namespaces().has(config.namespace))) {
throw new SoloError(`namespace ${config.namespace} does not exist`);
}
}
config.nodeAliases = helpers.parseNodeAliases(config.nodeAliasesUnparsed);
return config;
};
export const setupConfigBuilder = async function (argv, ctx, task) {
const config = this.getConfig(SETUP_CONFIGS_NAME, argv.flags, [
'nodeAliases',
'podRefs',
'namespace',
'consensusNodes',
'contexts',
]);
config.namespace = await resolveNamespaceFromDeployment(this.parent.localConfig, this.configManager, task);
config.nodeAliases = helpers.parseNodeAliases(config.nodeAliasesUnparsed);
config.consensusNodes = this.parent.getConsensusNodes();
await initializeSetup(config, this.k8Factory);
// set config in the context for later tasks to use
ctx.config = config;
return ctx.config;
};
//# sourceMappingURL=configs.js.map