UNPKG

@hashgraph/solo

Version:

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

148 lines 9.1 kB
// SPDX-License-Identifier: Apache-2.0 import { main } from '../../../../src/index.js'; import { Flags } from '../../../../src/commands/flags.js'; import { Duration } from '../../../../src/core/time/duration.js'; import { BaseCommandTest } from './base-command-test.js'; import { BlockCommandDefinition } from '../../../../src/commands/command-definitions/block-command-definition.js'; import * as constants from '../../../../src/core/constants.js'; import { expect } from 'chai'; import { exec } from 'node:child_process'; import { promisify } from 'node:util'; import { HEDERA_HAPI_PATH } from '../../../../src/core/constants.js'; import { K8Helper } from '../../../../src/business/utils/k8-helper.js'; import { sleep } from '../../../../src/core/helpers.js'; import { OperatingSystem } from '../../../../src/business/utils/operating-system.js'; export class BlockNodeTest extends BaseCommandTest { static soloBlockNodeDeployArgv(testName, deployment, clusterReference, enableLocalBuildPathTesting, localBuildReleaseTag, nodeAliases) { const { newArgv, argvPushGlobalFlags, optionFromFlag } = BlockNodeTest; const argv = newArgv(); argv.push(BlockCommandDefinition.COMMAND_NAME, BlockCommandDefinition.NODE_SUBCOMMAND_NAME, BlockCommandDefinition.NODE_ADD, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.clusterRef), clusterReference); if (enableLocalBuildPathTesting) { argv.push(optionFromFlag(Flags.releaseTag), localBuildReleaseTag); } if (nodeAliases !== undefined && nodeAliases.length > 0) { const stringBuilder = []; for (const nodeAlias of nodeAliases) { stringBuilder.push(`${nodeAlias}=1`); } argv.push(optionFromFlag(Flags.priorityMapping), stringBuilder.join(',')); } argvPushGlobalFlags(argv, testName, false, true); return argv; } static soloBlockNodeAddExternalArgv(testName, deployment, clusterReference, address, nodeAliases) { const { newArgv, argvPushGlobalFlags, optionFromFlag } = BlockNodeTest; const argv = newArgv(); argv.push(BlockCommandDefinition.COMMAND_NAME, BlockCommandDefinition.NODE_SUBCOMMAND_NAME, BlockCommandDefinition.NODE_ADD_EXTERNAL, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.clusterRef), clusterReference, optionFromFlag(Flags.externalBlockNodeAddress), address); if (nodeAliases !== undefined && nodeAliases.length > 0) { const stringBuilder = []; for (const nodeAlias of nodeAliases) { stringBuilder.push(`${nodeAlias}=1`); } argv.push(optionFromFlag(Flags.priorityMapping), stringBuilder.join(',')); } argvPushGlobalFlags(argv, testName, false, true); return argv; } static soloBlockNodeDestroyArgv(testName, deployment, clusterReference) { const { newArgv, argvPushGlobalFlags, optionFromFlag } = BlockNodeTest; const argv = newArgv(); argv.push(BlockCommandDefinition.COMMAND_NAME, BlockCommandDefinition.NODE_SUBCOMMAND_NAME, BlockCommandDefinition.NODE_DESTROY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.clusterRef), clusterReference, optionFromFlag(Flags.force), optionFromFlag(Flags.quiet), optionFromFlag(Flags.devMode)); argvPushGlobalFlags(argv, testName, false, true); return argv; } static soloBlockNodeDeleteExternalArgv(testName, deployment, clusterReference, id) { const { newArgv, argvPushGlobalFlags, optionFromFlag } = BlockNodeTest; const argv = newArgv(); argv.push(BlockCommandDefinition.COMMAND_NAME, BlockCommandDefinition.NODE_SUBCOMMAND_NAME, BlockCommandDefinition.NODE_DELETE_EXTERNAL, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.clusterRef), clusterReference, optionFromFlag(Flags.force), optionFromFlag(Flags.quiet), optionFromFlag(Flags.devMode)); if (id !== undefined) { argv.push(optionFromFlag(Flags.id), id.toString()); } argvPushGlobalFlags(argv, testName); return argv; } static add(options, nodeAliases) { const { testName, deployment, clusterReferenceNameArray, localBuildReleaseTag, enableLocalBuildPathTesting } = options; const { soloBlockNodeDeployArgv } = BlockNodeTest; it(`${testName}: block node add`, async () => { await main(soloBlockNodeDeployArgv(testName, deployment, clusterReferenceNameArray[0], enableLocalBuildPathTesting, localBuildReleaseTag, nodeAliases)); // Block node add can exceed 5 minutes on CI when image/chart pulls are slow. }).timeout(Duration.ofMinutes(10).toMillis()); } static addExternal(options, address, nodeAliases) { const { testName, deployment, clusterReferenceNameArray } = options; const { soloBlockNodeAddExternalArgv } = BlockNodeTest; it(`${testName}: block node add-external`, async () => { await main(soloBlockNodeAddExternalArgv(testName, deployment, clusterReferenceNameArray[0], address, nodeAliases)); }).timeout(Duration.ofMinutes(5).toMillis()); } static deleteExternal(options, id) { const { testName, deployment, clusterReferenceNameArray } = options; const { soloBlockNodeDeleteExternalArgv } = BlockNodeTest; it(`${testName}: block node delete-external`, async () => { await main(soloBlockNodeDeleteExternalArgv(testName, deployment, clusterReferenceNameArray[1], id)); }).timeout(Duration.ofMinutes(5).toMillis()); } static destroy(options) { const { testName, deployment, clusterReferenceNameArray } = options; const { soloBlockNodeDestroyArgv } = BlockNodeTest; it(`${testName}: block node destroy`, async () => { await main(soloBlockNodeDestroyArgv(testName, deployment, clusterReferenceNameArray[1])); }).timeout(Duration.ofMinutes(5).toMillis()); } static testBlockNode(options, blockNodeId = 1) { const { namespace, contexts, testName } = options; const execAsync = promisify(exec); it(`${testName}: test block node connection for block node ${blockNodeId}`, async () => { const pod = await new K8Helper(contexts[0]).getBlockNodePod(namespace, blockNodeId); const srv = await pod.portForward(constants.BLOCK_NODE_PORT, constants.BLOCK_NODE_PORT); // Sleep to allow the port-forward to be established before attempting to connect await sleep(Duration.ofSeconds(5)); const commandOptions = { cwd: './test/data', maxBuffer: 50 * 1024 * 1024, encoding: 'utf8', }; // Make script executable (no-op on Windows; chmod is not available) if (!OperatingSystem.isWin32()) { await execAsync('chmod +x ./get-block.sh', commandOptions); } // Execute script (use bash explicitly on Windows since .sh files have no default handler) const scriptCommand = OperatingSystem.isWin32() ? 'bash ./get-block.sh 1' : './get-block.sh 1'; const scriptStd = await execAsync(scriptCommand, commandOptions); expect(scriptStd.stderr).to.equal(''); expect(scriptStd.stdout).to.include('"status": "SUCCESS"'); await pod.stopPortForward(srv); }).timeout(Duration.ofMinutes(2).toMillis()); } static verifyBlockNodesJson(options, nodeAlias, blockNodeIds, excludedBlockNodeIds = [], { expectedExternalAddress, expectedExternalPort, unexpectedExternalAddress, unexpectedExternalPort, }) { const { namespace, contexts, testName } = options; it(`${testName}: verify block-nodes.json for ${nodeAlias}`, async () => { const root = await new K8Helper(contexts[0]).getConsensusNodeRootContainer(namespace, nodeAlias); const output = await root.execContainer([ 'bash', '-c', `cat ${HEDERA_HAPI_PATH}/data/config/block-nodes.json`, ]); for (const blockNodeId of blockNodeIds) { expect(output).to.include(`block-node-${blockNodeId}`); } for (const excludedBlockNodeId of excludedBlockNodeIds) { expect(output).to.not.include(`block-node-${excludedBlockNodeId}`); } if (expectedExternalAddress !== undefined) { expect(output).to.include(expectedExternalAddress); } if (expectedExternalPort !== undefined) { expect(output).to.include(expectedExternalPort.toString()); } if (unexpectedExternalAddress !== undefined) { expect(output).not.to.include(unexpectedExternalAddress); } if (unexpectedExternalPort !== undefined) { expect(output).not.to.include(unexpectedExternalPort.toString()); } }); } } //# sourceMappingURL=block-node-test.js.map