@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
95 lines • 6.59 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import { BaseCommandTest } from './base-command-test.js';
import { main } from '../../../../src/index.js';
import { InjectTokens } from '../../../../src/core/dependency-injection/inject-tokens.js';
import { Duration } from '../../../../src/core/time/duration.js';
import { container } from 'tsyringe-neo';
import { expect } from 'chai';
import { Flags as flags, Flags } from '../../../../src/commands/flags.js';
import { ConsensusCommandDefinition } from '../../../../src/commands/command-definitions/consensus-command-definition.js';
import { it } from 'mocha';
import { sleep } from '../../../../src/core/helpers.js';
import * as constants from '../../../../src/core/constants.js';
export class NetworkTest extends BaseCommandTest {
static soloNetworkDeployArgv(testName, deployment, enableLocalBuildPathTesting, localBuildReleaseTag, loadBalancerEnabled, releaseTagOverride) {
const { newArgv, argvPushGlobalFlags, optionFromFlag } = NetworkTest;
const argv = newArgv();
argv.push(ConsensusCommandDefinition.COMMAND_NAME, ConsensusCommandDefinition.NETWORK_SUBCOMMAND_NAME, ConsensusCommandDefinition.NETWORK_DEPLOY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(flags.persistentVolumeClaims), optionFromFlag(Flags.serviceMonitor), optionFromFlag(Flags.podLog));
// have to enable load balancer to resolve cross cluster in multi-cluster
if (loadBalancerEnabled) {
argv.push(optionFromFlag(Flags.loadBalancerEnabled));
}
if (releaseTagOverride) {
argv.push(optionFromFlag(Flags.releaseTag), releaseTagOverride);
}
else if (enableLocalBuildPathTesting) {
argv.push(optionFromFlag(Flags.releaseTag), localBuildReleaseTag);
}
argvPushGlobalFlags(argv, testName, true, true);
return argv;
}
static deploy(options, releaseTagOverride) {
const { testName, deployment, namespace, contexts, enableLocalBuildPathTesting, localBuildReleaseTag, loadBalancerEnabled, clusterReferenceNameArray, consensusNodesCount, } = options;
const { soloNetworkDeployArgv } = NetworkTest;
it(`${testName}: consensus network deploy`, async () => {
await main(soloNetworkDeployArgv(testName, deployment, enableLocalBuildPathTesting, localBuildReleaseTag, loadBalancerEnabled, releaseTagOverride));
const k8Factory = container.resolve(InjectTokens.K8Factory);
const clusterCount = clusterReferenceNameArray.length;
const base = Math.floor(consensusNodesCount / clusterCount);
const remainder = consensusNodesCount % clusterCount;
const nodeCountsPerCluster = clusterReferenceNameArray.map((_, index) => index < remainder ? base + 1 : base);
for (const [index, context_] of contexts.entries()) {
const nodeCount = nodeCountsPerCluster[index];
const namespaceExists = await k8Factory.getK8(context_).namespaces().has(namespace);
expect(namespaceExists, `namespace ${namespace} should exist in ${context_}`).to.be.true;
const pods = await k8Factory
.getK8(context_)
.pods()
.list(namespace, ['solo.hedera.com/type=network-node']);
expect(pods.length, `expected exactly ${nodeCount} network-node pod in namespace ${namespace} for context ${context_}`).to.equal(nodeCount);
}
}).timeout(Duration.ofMinutes(5).toMillis());
}
static soloConsensusNetworkDestroyArgv(testName, deployment) {
const { newArgv, argvPushGlobalFlags, optionFromFlag } = NetworkTest;
const argv = newArgv();
argv.push(ConsensusCommandDefinition.COMMAND_NAME, ConsensusCommandDefinition.NETWORK_SUBCOMMAND_NAME, ConsensusCommandDefinition.NETWORK_DESTROY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.deletePvcs), optionFromFlag(Flags.deleteSecrets), optionFromFlag(Flags.force), optionFromFlag(Flags.quiet));
argvPushGlobalFlags(argv, testName, false, true);
return argv;
}
static destroy(options) {
const { testName, deployment } = options;
const { soloConsensusNetworkDestroyArgv } = NetworkTest;
it(`${testName}: consensus network destroy`, async () => {
await main(soloConsensusNetworkDestroyArgv(testName, deployment));
}).timeout(Duration.ofMinutes(10).toMillis());
it(`${testName}: consensus network destroy should success`, async () => {
const { namespace, contexts: contextRecord, testLogger: logger } = options;
const k8Factory = container.resolve(InjectTokens.K8Factory);
const chartManager = container.resolve(InjectTokens.ChartManager);
const contexts = [...contextRecord.values()]; // get all contexts
async function getPodsCountInMultipleNamespaces(label) {
return await Promise.all(contexts.map((context) => k8Factory.getK8(context).pods().list(namespace, label))).then((results) => results.flat().length);
}
async function waitUntilPodsGone(label) {
logger.showUser(`Waiting for pod ${label} to be gone`);
while (true) {
const podsCount = await getPodsCountInMultipleNamespaces(label);
if (podsCount === 0) {
break;
}
await sleep(Duration.ofSeconds(3));
}
}
await waitUntilPodsGone(['solo.hedera.com/type=network-node']);
await waitUntilPodsGone(['app=minio']);
const isChartInstalled = await chartManager.isChartInstalled(namespace, constants.SOLO_DEPLOYMENT_CHART);
expect(isChartInstalled).to.be.false;
await expect(k8Factory.getK8(contexts[0]).pvcs().list(namespace, []), 'PVCs should be deleted in cluster[0]').eventually.to.have.lengthOf(0);
await expect(k8Factory.getK8(contexts[1]).pvcs().list(namespace, []), 'PVCs should be deleted in cluster[1]').eventually.to.have.lengthOf(0);
await expect(k8Factory.getK8(contexts[0]).secrets().list(namespace), 'Secrets should be deleted in cluster[0]').eventually.to.have.lengthOf(0);
await expect(k8Factory.getK8(contexts[1]).secrets().list(namespace), 'Secrets should be deleted in cluster[1]').eventually.to.have.lengthOf(0);
}).timeout(Duration.ofMinutes(4).toMillis());
}
}
//# sourceMappingURL=network-test.js.map