@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
697 lines • 33.3 kB
JavaScript
/**
* SPDX-License-Identifier: Apache-2.0
*/
import * as helpers from '../../core/helpers.js';
import * as NodeFlags from './flags.js';
import { addConfigBuilder, deleteConfigBuilder, downloadGeneratedFilesConfigBuilder, keysConfigBuilder, logsConfigBuilder, prepareUpgradeConfigBuilder, refreshConfigBuilder, setupConfigBuilder, startConfigBuilder, statesConfigBuilder, stopConfigBuilder, updateConfigBuilder, upgradeConfigBuilder, } from './configs.js';
import * as constants from '../../core/constants.js';
import { IllegalArgumentError, SoloError } from '../../core/errors.js';
import { ComponentType, ConsensusNodeStates } from '../../core/config/remote/enumerations.js';
import { NodeSubcommandType } from '../../core/enumerations.js';
import { NodeHelper } from './helper.js';
import { ConsensusNodeComponent } from '../../core/config/remote/components/consensus_node_component.js';
import chalk from 'chalk';
export class NodeCommandHandlers {
accountManager;
configManager;
platformInstaller;
logger;
k8Factory;
tasks;
leaseManager;
remoteConfigManager;
contexts;
consensusNodes;
getConfig;
prepareChartPath;
parent;
constructor(opts) {
if (!opts || !opts.accountManager)
throw new IllegalArgumentError('An instance of core/AccountManager is required', opts.accountManager);
if (!opts || !opts.configManager)
throw new Error('An instance of core/ConfigManager is required');
if (!opts || !opts.logger)
throw new Error('An instance of core/Logger is required');
if (!opts || !opts.tasks)
throw new Error('An instance of NodeCommandTasks is required');
if (!opts || !opts.k8Factory)
throw new Error('An instance of core/K8Factory is required');
if (!opts || !opts.platformInstaller)
throw new IllegalArgumentError('An instance of core/PlatformInstaller is required', opts.platformInstaller);
this.logger = opts.logger;
this.tasks = opts.tasks;
this.accountManager = opts.accountManager;
this.configManager = opts.configManager;
this.k8Factory = opts.k8Factory;
this.platformInstaller = opts.platformInstaller;
this.leaseManager = opts.leaseManager;
this.remoteConfigManager = opts.remoteConfigManager;
this.getConfig = opts.parent.getConfig.bind(opts.parent);
this.prepareChartPath = opts.parent.prepareChartPath.bind(opts.parent);
this.parent = opts.parent;
}
static ADD_CONTEXT_FILE = 'node-add.json';
static DELETE_CONTEXT_FILE = 'node-delete.json';
static UPDATE_CONTEXT_FILE = 'node-update.json';
static UPGRADE_CONTEXT_FILE = 'node-upgrade.json';
init() {
this.consensusNodes = this.parent.getConsensusNodes();
this.contexts = this.parent.getContexts();
}
/** ******** Task Lists **********/
deletePrepareTaskList(argv, lease) {
return [
this.tasks.initialize(argv, deleteConfigBuilder.bind(this), lease),
this.validateSingleNodeState({ excludedStates: [] }),
this.tasks.identifyExistingNodes(),
this.tasks.loadAdminKey(),
this.tasks.prepareUpgradeZip(),
this.tasks.checkExistingNodesStakedAmount(),
];
}
deleteSubmitTransactionsTaskList(argv) {
return [
this.tasks.sendNodeDeleteTransaction(),
this.tasks.sendPrepareUpgradeTransaction(),
this.tasks.sendFreezeUpgradeTransaction(),
];
}
deleteExecuteTaskList(argv) {
return [
this.tasks.checkAllNodesAreFrozen('existingNodeAliases'),
this.tasks.downloadNodeGeneratedFiles(),
this.tasks.prepareStagingDirectory('existingNodeAliases'),
this.tasks.refreshNodeList(),
this.tasks.copyNodeKeysToSecrets(),
this.tasks.getNodeLogsAndConfigs(),
this.tasks.updateChartWithConfigMap('Delete network node', NodeSubcommandType.DELETE),
this.tasks.killNodes(),
this.tasks.sleep('Give time for pods to come up after being killed', 20000),
this.tasks.checkNodePodsAreRunning(),
this.tasks.populateServiceMap(),
this.tasks.fetchPlatformSoftware('allNodeAliases'),
this.tasks.setupNetworkNodes('allNodeAliases', false),
this.tasks.startNodes('allNodeAliases'),
this.tasks.enablePortForwarding(),
this.tasks.checkAllNodesAreActive('allNodeAliases'),
this.tasks.checkAllNodeProxiesAreActive(),
this.tasks.triggerStakeWeightCalculate(NodeSubcommandType.DELETE),
this.tasks.finalize(),
];
}
addPrepareTasks(argv, lease) {
return [
this.tasks.initialize(argv, addConfigBuilder.bind(this), lease),
// TODO instead of validating the state we need to do a remote config add component, and we will need to manually
// the nodeAlias based on the next available node ID + 1
// this.validateSingleNodeState({excludedStates: []}),
this.tasks.checkPVCsEnabled(),
this.tasks.identifyExistingNodes(),
this.tasks.determineNewNodeAccountNumber(),
this.tasks.copyGrpcTlsCertificates(),
this.tasks.generateGossipKey(),
this.tasks.generateGrpcTlsKey(),
this.tasks.loadSigningKeyCertificate(),
this.tasks.computeMTLSCertificateHash(),
this.tasks.prepareGossipEndpoints(),
this.tasks.prepareGrpcServiceEndpoints(),
this.tasks.prepareUpgradeZip(),
this.tasks.checkExistingNodesStakedAmount(),
];
}
addSubmitTransactionsTasks(argv) {
return [
this.tasks.sendNodeCreateTransaction(),
this.tasks.sendPrepareUpgradeTransaction(),
this.tasks.sendFreezeUpgradeTransaction(),
];
}
addExecuteTasks(argv) {
return [
this.tasks.checkAllNodesAreFrozen('existingNodeAliases'),
this.tasks.downloadNodeGeneratedFiles(),
this.tasks.prepareStagingDirectory('allNodeAliases'),
this.tasks.copyNodeKeysToSecrets(),
this.tasks.getNodeLogsAndConfigs(),
this.tasks.updateChartWithConfigMap('Deploy new network node', NodeSubcommandType.ADD),
this.tasks.killNodes(),
this.tasks.checkNodePodsAreRunning(),
this.tasks.populateServiceMap(),
this.tasks.fetchPlatformSoftware('allNodeAliases'),
this.tasks.downloadLastState(),
this.tasks.uploadStateToNewNode(),
this.tasks.setupNetworkNodes('allNodeAliases', false),
this.tasks.startNodes('allNodeAliases'),
this.tasks.enablePortForwarding(),
this.tasks.checkAllNodesAreActive('allNodeAliases'),
this.tasks.checkAllNodeProxiesAreActive(),
this.tasks.stakeNewNode(),
this.tasks.triggerStakeWeightCalculate(NodeSubcommandType.ADD),
this.tasks.finalize(),
];
}
updatePrepareTasks(argv, lease) {
return [
this.tasks.initialize(argv, updateConfigBuilder.bind(this), lease),
this.validateSingleNodeState({ excludedStates: [] }),
this.tasks.identifyExistingNodes(),
this.tasks.loadAdminKey(),
this.tasks.prepareUpgradeZip(),
this.tasks.checkExistingNodesStakedAmount(),
];
}
updateSubmitTransactionsTasks(argv) {
return [
this.tasks.sendNodeUpdateTransaction(),
this.tasks.sendPrepareUpgradeTransaction(),
this.tasks.sendFreezeUpgradeTransaction(),
];
}
updateExecuteTasks(argv) {
return [
this.tasks.checkAllNodesAreFrozen('existingNodeAliases'),
this.tasks.downloadNodeGeneratedFiles(),
this.tasks.prepareStagingDirectory('allNodeAliases'),
this.tasks.copyNodeKeysToSecrets(),
this.tasks.getNodeLogsAndConfigs(),
this.tasks.updateChartWithConfigMap('Update chart to use new configMap due to account number change', NodeSubcommandType.UPDATE, (ctx) => !ctx.config.newAccountNumber && !ctx.config.debugNodeAlias),
this.tasks.killNodesAndUpdateConfigMap(),
this.tasks.checkNodePodsAreRunning(),
this.tasks.fetchPlatformSoftware('allNodeAliases'),
this.tasks.setupNetworkNodes('allNodeAliases', false),
this.tasks.startNodes('allNodeAliases'),
this.tasks.enablePortForwarding(),
this.tasks.checkAllNodesAreActive('allNodeAliases'),
this.tasks.checkAllNodeProxiesAreActive(),
this.tasks.triggerStakeWeightCalculate(NodeSubcommandType.UPDATE),
this.tasks.finalize(),
];
}
upgradePrepareTasks(argv, lease) {
return [
this.tasks.initialize(argv, upgradeConfigBuilder.bind(this), lease),
this.validateAllNodeStates({ excludedStates: [] }),
this.tasks.identifyExistingNodes(),
this.tasks.loadAdminKey(),
this.tasks.prepareUpgradeZip(),
this.tasks.checkExistingNodesStakedAmount(),
];
}
upgradeSubmitTransactionsTasks(argv) {
return [this.tasks.sendPrepareUpgradeTransaction(), this.tasks.sendFreezeUpgradeTransaction()];
}
upgradeExecuteTasks(argv) {
return [
this.tasks.checkAllNodesAreFrozen('existingNodeAliases'),
this.tasks.downloadNodeUpgradeFiles(),
this.tasks.getNodeLogsAndConfigs(),
this.tasks.startNodes('allNodeAliases'),
this.tasks.enablePortForwarding(),
this.tasks.checkAllNodesAreActive('allNodeAliases'),
this.tasks.checkAllNodeProxiesAreActive(),
this.tasks.finalize(),
];
}
/** ******** Handlers **********/
async prepareUpgrade(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DEFAULT_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, prepareUpgradeConfigBuilder.bind(this), lease),
this.tasks.prepareUpgradeZip(),
this.tasks.sendPrepareUpgradeTransaction(),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in preparing node upgrade', lease);
await action(argv, this);
return true;
}
async freezeUpgrade(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DEFAULT_FLAGS);
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, prepareUpgradeConfigBuilder.bind(this), null),
this.tasks.prepareUpgradeZip(),
this.tasks.sendFreezeUpgradeTransaction(),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in executing node freeze upgrade', null);
await action(argv, this);
return true;
}
async downloadGeneratedFiles(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DEFAULT_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, downloadGeneratedFilesConfigBuilder.bind(this), lease),
this.tasks.identifyExistingNodes(),
this.tasks.downloadNodeGeneratedFiles(),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in downloading generated files', lease);
await action(argv, this);
return true;
}
async update(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPDATE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.updatePrepareTasks(argv, lease),
...this.updateSubmitTransactionsTasks(argv),
...this.updateExecuteTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in updating nodes', lease);
await action(argv, this);
return true;
}
async updatePrepare(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPDATE_PREPARE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.updatePrepareTasks(argv, lease),
this.tasks.saveContextData(argv, NodeCommandHandlers.UPDATE_CONTEXT_FILE, NodeHelper.updateSaveContextParser),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in preparing node update', lease);
await action(argv, this);
return true;
}
async updateSubmitTransactions(argv) {
const lease = await this.leaseManager.create();
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPDATE_SUBMIT_TRANSACTIONS_FLAGS);
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, updateConfigBuilder.bind(this), lease),
this.tasks.loadContextData(argv, NodeCommandHandlers.UPDATE_CONTEXT_FILE, NodeHelper.updateLoadContextParser),
...this.updateSubmitTransactionsTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in submitting transactions for node update', lease);
await action(argv, this);
return true;
}
async updateExecute(argv) {
const lease = await this.leaseManager.create();
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPDATE_EXECUTE_FLAGS);
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, updateConfigBuilder.bind(this), lease, false),
this.tasks.loadContextData(argv, NodeCommandHandlers.UPDATE_CONTEXT_FILE, NodeHelper.updateLoadContextParser),
...this.updateExecuteTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in executing network upgrade', lease);
await action(argv, this);
return true;
}
async upgradePrepare(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPGRADE_PREPARE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.upgradePrepareTasks(argv, lease),
this.tasks.saveContextData(argv, NodeCommandHandlers.UPGRADE_CONTEXT_FILE, NodeHelper.upgradeSaveContextParser),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in preparing node upgrade', lease);
await action(argv, this);
return true;
}
async upgradeSubmitTransactions(argv) {
const lease = await this.leaseManager.create();
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPGRADE_SUBMIT_TRANSACTIONS_FLAGS);
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, upgradeConfigBuilder.bind(this), lease),
this.tasks.loadContextData(argv, NodeCommandHandlers.UPGRADE_CONTEXT_FILE, NodeHelper.upgradeLoadContextParser),
...this.upgradeSubmitTransactionsTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in submitting transactions for node upgrade', lease);
await action(argv, this);
return true;
}
async upgradeExecute(argv) {
const lease = await this.leaseManager.create();
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPGRADE_FLAGS);
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, upgradeConfigBuilder.bind(this), lease, false),
this.tasks.loadContextData(argv, NodeCommandHandlers.UPGRADE_CONTEXT_FILE, NodeHelper.upgradeLoadContextParser),
...this.upgradeExecuteTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in executing network upgrade', lease);
await action(argv, this);
return true;
}
async upgrade(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.UPGRADE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.upgradePrepareTasks(argv, lease),
...this.upgradeSubmitTransactionsTasks(argv),
...this.upgradeExecuteTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in upgrade network', lease);
await action(argv, this);
return true;
}
async delete(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DELETE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.deletePrepareTaskList(argv, lease),
...this.deleteSubmitTransactionsTaskList(argv),
...this.deleteExecuteTaskList(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in deleting nodes', lease);
await action(argv, this);
return true;
}
async deletePrepare(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DELETE_PREPARE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.deletePrepareTaskList(argv, lease),
this.tasks.saveContextData(argv, NodeCommandHandlers.DELETE_CONTEXT_FILE, NodeHelper.deleteSaveContextParser),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in preparing to delete a node', lease);
await action(argv, this);
return true;
}
async deleteSubmitTransactions(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DELETE_SUBMIT_TRANSACTIONS_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, deleteConfigBuilder.bind(this), lease),
this.tasks.loadContextData(argv, NodeCommandHandlers.DELETE_CONTEXT_FILE, NodeHelper.deleteLoadContextParser),
...this.deleteSubmitTransactionsTaskList(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in deleting a node', lease);
await action(argv, this);
return true;
}
async deleteExecute(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.DELETE_EXECUTE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, deleteConfigBuilder.bind(this), lease, false),
this.tasks.loadContextData(argv, NodeCommandHandlers.DELETE_CONTEXT_FILE, NodeHelper.deleteLoadContextParser),
...this.deleteExecuteTaskList(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in deleting a node', lease);
await action(argv, this);
return true;
}
async add(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.ADD_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([...this.addPrepareTasks(argv, lease), ...this.addSubmitTransactionsTasks(argv), ...this.addExecuteTasks(argv)], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in adding node', lease);
await action(argv, this);
return true;
}
async addPrepare(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.ADD_PREPARE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
...this.addPrepareTasks(argv, lease),
this.tasks.saveContextData(argv, NodeCommandHandlers.ADD_CONTEXT_FILE, helpers.addSaveContextParser),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in preparing node', lease);
await action(argv, this);
return true;
}
async addSubmitTransactions(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.ADD_SUBMIT_TRANSACTIONS_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, addConfigBuilder.bind(this), lease),
this.tasks.loadContextData(argv, NodeCommandHandlers.ADD_CONTEXT_FILE, helpers.addLoadContextParser),
...this.addSubmitTransactionsTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, '`Error in submitting transactions to node', lease);
await action(argv, this);
return true;
}
async addExecute(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.ADD_EXECUTE_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, addConfigBuilder.bind(this), lease, false),
this.tasks.identifyExistingNodes(),
this.tasks.loadContextData(argv, NodeCommandHandlers.ADD_CONTEXT_FILE, helpers.addLoadContextParser),
...this.addExecuteTasks(argv),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in adding node', lease);
await action(argv, this);
return true;
}
async logs(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.LOGS_FLAGS);
const action = this.parent.commandActionBuilder([this.tasks.initialize(argv, logsConfigBuilder.bind(this), null), this.tasks.getNodeLogsAndConfigs()], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in downloading log from nodes', null);
await action(argv, this);
return true;
}
async states(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.STATES_FLAGS);
const action = this.parent.commandActionBuilder([this.tasks.initialize(argv, statesConfigBuilder.bind(this), null), this.tasks.getNodeStateFiles()], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in downloading states from nodes', null);
await action(argv, this);
return true;
}
async refresh(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.REFRESH_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, refreshConfigBuilder.bind(this), lease),
this.validateAllNodeStates({
acceptedStates: [ConsensusNodeStates.STARTED, ConsensusNodeStates.SETUP, ConsensusNodeStates.INITIALIZED],
}),
this.tasks.identifyNetworkPods(),
this.tasks.dumpNetworkNodesSaveState(),
this.tasks.fetchPlatformSoftware('nodeAliases'),
this.tasks.setupNetworkNodes('nodeAliases', true),
this.tasks.startNodes('nodeAliases'),
this.tasks.checkAllNodesAreActive('nodeAliases'),
this.tasks.checkNodeProxiesAreActive(),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in refreshing nodes', lease);
await action(argv, this);
return true;
}
async keys(argv) {
this.init();
argv = helpers.addFlagsToArgv(argv, NodeFlags.KEYS_FLAGS);
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, keysConfigBuilder.bind(this), null),
this.tasks.generateGossipKeys(),
this.tasks.generateGrpcTlsKeys(),
this.tasks.finalize(),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error generating keys', null);
await action(argv, this);
return true;
}
async stop(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.STOP_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, stopConfigBuilder.bind(this), lease),
this.validateAllNodeStates({
acceptedStates: [ConsensusNodeStates.STARTED, ConsensusNodeStates.SETUP],
}),
this.tasks.identifyNetworkPods(1),
this.tasks.stopNodes(),
this.changeAllNodeStates(ConsensusNodeStates.INITIALIZED),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error stopping node', lease);
await action(argv, this);
return true;
}
async start(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.START_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, startConfigBuilder.bind(this), lease),
this.validateAllNodeStates({ acceptedStates: [ConsensusNodeStates.SETUP] }),
this.tasks.identifyExistingNodes(),
this.tasks.uploadStateFiles((ctx) => ctx.config.stateFile.length === 0),
this.tasks.startNodes('nodeAliases'),
this.tasks.enablePortForwarding(),
this.tasks.checkAllNodesAreActive('nodeAliases'),
this.tasks.checkNodeProxiesAreActive(),
this.changeAllNodeStates(ConsensusNodeStates.STARTED),
this.tasks.addNodeStakes(),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error starting node', lease);
await action(argv, this);
return true;
}
async setup(argv) {
argv = helpers.addFlagsToArgv(argv, NodeFlags.SETUP_FLAGS);
const lease = await this.leaseManager.create();
const action = this.parent.commandActionBuilder([
this.tasks.initialize(argv, setupConfigBuilder.bind(this), lease),
this.validateAllNodeStates({
acceptedStates: [ConsensusNodeStates.INITIALIZED],
}),
this.tasks.identifyNetworkPods(),
this.tasks.fetchPlatformSoftware('nodeAliases'),
this.tasks.setupNetworkNodes('nodeAliases', true),
this.changeAllNodeStates(ConsensusNodeStates.SETUP),
], {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
}, 'Error in setting up nodes', lease);
await action(argv, this);
return true;
}
/** Removes the consensus node, envoy and haproxy components from remote config. */
removeNodeAndProxies() {
return {
skip: () => !this.remoteConfigManager.isLoaded(),
title: 'Remove node and proxies from remote config',
task: async () => {
await this.remoteConfigManager.modify(async (remoteConfig) => {
remoteConfig.components.remove('Consensus node name', ComponentType.ConsensusNode);
remoteConfig.components.remove('Envoy proxy name', ComponentType.EnvoyProxy);
remoteConfig.components.remove('HaProxy name', ComponentType.HaProxy);
});
},
};
}
/**
* Changes the state from all consensus nodes components in remote config.
*
* @param state - to which to change the consensus node component
*/
changeAllNodeStates(state) {
return {
title: `Change node state to ${state} in remote config`,
skip: () => !this.remoteConfigManager.isLoaded(),
task: async (ctx) => {
await this.remoteConfigManager.modify(async (remoteConfig) => {
const { config: { namespace }, } = ctx;
for (const consensusNode of ctx.config.consensusNodes) {
remoteConfig.components.edit(consensusNode.name, new ConsensusNodeComponent(consensusNode.name, consensusNode.cluster, namespace.name, state, consensusNode.nodeId));
}
});
},
};
}
/**
* Creates tasks to validate that each node state is either one of the accepted states or not one of the excluded.
*
* @param acceptedStates - the state at which the nodes can be, not matching any of the states throws an error
* @param excludedStates - the state at which the nodes can't be, matching any of the states throws an error
*/
validateAllNodeStates({ acceptedStates, excludedStates, }) {
return {
title: 'Validate nodes states',
skip: () => !this.remoteConfigManager.isLoaded(),
task: (ctx, task) => {
const nodeAliases = ctx.config.nodeAliases;
const components = this.remoteConfigManager.components;
const subTasks = nodeAliases.map(nodeAlias => ({
title: `Validating state for node ${nodeAlias}`,
task: (_, task) => {
const state = this.validateNodeState(nodeAlias, components, acceptedStates, excludedStates);
task.title += ` - ${chalk.green('valid state')}: ${chalk.cyan(state)}`;
},
}));
return task.newListr(subTasks, {
concurrent: false,
rendererOptions: { collapseSubtasks: false },
});
},
};
}
/**
* Creates tasks to validate that specific node state is either one of the accepted states or not one of the excluded.
*
* @param acceptedStates - the state at which the node can be, not matching any of the states throws an error
* @param excludedStates - the state at which the node can't be, matching any of the states throws an error
*/
validateSingleNodeState({ acceptedStates, excludedStates, }) {
return {
title: 'Validate nodes state',
skip: () => !this.remoteConfigManager.isLoaded(),
task: (ctx, task) => {
const nodeAlias = ctx.config.nodeAlias;
task.title += ` ${nodeAlias}`;
const components = this.remoteConfigManager.components;
const state = this.validateNodeState(nodeAlias, components, acceptedStates, excludedStates);
task.title += ` - ${chalk.green('valid state')}: ${chalk.cyan(state)}`;
},
};
}
/**
* @param nodeAlias - the alias of the node whose state to validate
* @param components - the component data wrapper
* @param acceptedStates - the state at which the node can be, not matching any of the states throws an error
* @param excludedStates - the state at which the node can't be, matching any of the states throws an error
*/
validateNodeState(nodeAlias, components, acceptedStates, excludedStates) {
let nodeComponent;
try {
nodeComponent = components.getComponent(ComponentType.ConsensusNode, nodeAlias);
}
catch {
throw new SoloError(`${nodeAlias} not found in remote config`);
}
// TODO: Enable once the states have been mapped
// if (acceptedStates && !acceptedStates.includes(nodeComponent.state)) {
// const errorMessageData =
// `accepted states: ${acceptedStates.join(', ')}, ` + `current state: ${nodeComponent.state}`;
//
// throw new SoloError(`${nodeAlias} has invalid state - ` + errorMessageData);
// }
//
// if (excludedStates && excludedStates.includes(nodeComponent.state)) {
// const errorMessageData =
// `excluded states: ${excludedStates.join(', ')}, ` + `current state: ${nodeComponent.state}`;
//
// throw new SoloError(`${nodeAlias} has invalid state - ` + errorMessageData);
// }
return nodeComponent.state;
}
}
//# sourceMappingURL=handlers.js.map