@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
136 lines • 7.38 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import { describe } from 'mocha';
import { resetForTest } from '../../test-container.js';
import { container } from 'tsyringe-neo';
import { InjectTokens } from '../../../src/core/dependency-injection/inject-tokens.js';
import fs from 'node:fs';
import { DEFAULT_LOCAL_CONFIG_FILE } from '../../../src/core/constants.js';
import { Duration } from '../../../src/core/time/duration.js';
import { PathEx } from '../../../src/business/utils/path-ex.js';
import { Client, AccountId, PrivateKey, Hbar, TransferTransaction, } from '@hiero-ledger/sdk';
import { EndToEndTestSuiteBuilder } from '../end-to-end-test-suite-builder.js';
import { main } from '../../../src/index.js';
import { BaseCommandTest } from './tests/base-command-test.js';
import { OneShotCommandDefinition } from '../../../src/commands/command-definitions/one-shot-command-definition.js';
import { MetricsServerImpl } from '../../../src/business/runtime-state/services/metrics-server-impl.js';
import * as constants from '../../../src/core/constants.js';
import { Flags } from '../../../src/commands/flags.js';
import { HelmMetricsServer } from '../../helpers/helm-metrics-server.js';
import { HelmMetalLoadBalancer } from '../../helpers/helm-metal-load-balancer.js';
import { DeploymentTest } from './tests/deployment-test.js';
const minimalSetup = process.env.SOLO_ONE_SHOT_MINIMAL_SETUP?.toLowerCase() === 'true';
const testName = minimalSetup ? 'one-shot-single-minimal' : 'one-shot-single';
const testTitle = 'One Shot Single E2E Test';
const endToEndTestSuite = new EndToEndTestSuiteBuilder()
.withTestName(testName)
.withTestSuiteName(`${testTitle} Suite`)
.withNamespace(testName)
.withDeployment(`${testName}-deployment`)
.withClusterCount(1)
.withMinimalSetup(process.env.SOLO_ONE_SHOT_MINIMAL_SETUP?.toLowerCase() === 'true')
.withTestSuiteCallback((options) => {
describe(testTitle, () => {
const { testCacheDirectory, testLogger, namespace, contexts, deployment } = options;
// TODO the kube config context causes issues if it isn't one of the selected clusters we are deploying to
before(async () => {
fs.rmSync(testCacheDirectory, { recursive: true, force: true });
try {
fs.rmSync(PathEx.joinWithRealPath(testCacheDirectory, '..', DEFAULT_LOCAL_CONFIG_FILE), {
force: true,
});
}
catch {
// allowed to fail if the file doesn't exist
}
if (!fs.existsSync(testCacheDirectory)) {
fs.mkdirSync(testCacheDirectory, { recursive: true });
}
resetForTest(namespace.name, testCacheDirectory, false);
for (const item of contexts) {
try {
const k8Client = container.resolve(InjectTokens.K8Factory).getK8(item);
await k8Client.namespaces().delete(namespace);
}
catch {
// allowed to fail if the namespace doesn't exist
}
}
testLogger.info(`${testName}: starting ${testName} e2e test`);
}).timeout(Duration.ofMinutes(5).toMillis());
after(async () => {
await main(soloDeploymentDiagnosticsLogs(testName, deployment));
testLogger.info(`${testName}: beginning ${testName}: destroy`);
await main(soloOneShotDestroy(testName));
testLogger.info(`${testName}: finished ${testName}: destroy`);
}).timeout(Duration.ofMinutes(5).toMillis());
// TODO pass in namespace for cache directory for proper destroy on restart
it(`${testName}: deploy`, async () => {
testLogger.info(`${testName}: beginning ${testName}: deploy`);
await main(soloOneShotDeploy(testName, deployment, options.minimalSetup));
testLogger.info(`${testName}: finished ${testName}: deploy`);
}).timeout(Duration.ofMinutes(20).toMillis());
it(`${testName}: show deployment`, async () => {
testLogger.info(`${testName}: beginning ${testName}: show deployment`);
await main(soloOneShotShowDeployment(testName, deployment));
testLogger.info(`${testName}: finished ${testName}: show deployment`);
}).timeout(Duration.ofMinutes(5).toMillis());
DeploymentTest.verifyDeploymentConfigPorts(options);
it('Should perform a simple TransferTransaction', async () => {
// These should be set in your environment or test config
const operatorId = AccountId.fromString('0.0.2');
const operatorKey = PrivateKey.fromStringED25519(constants.GENESIS_KEY);
const recipientId = AccountId.fromString('0.0.3');
const client = Client.forNetwork({ 'localhost:35211': '0.0.3' }).setOperator(operatorId, operatorKey);
const tx = await new TransferTransaction()
.addHbarTransfer(operatorId, new Hbar(-1))
.addHbarTransfer(recipientId, new Hbar(1))
.execute(client);
const receipt = await tx.getReceipt(client);
if (receipt.status.toString() !== 'SUCCESS') {
throw new Error(`TransferTransaction failed: ${receipt.status}`);
}
});
it('Should write log metrics', async () => {
if (minimalSetup) {
await HelmMetricsServer.installMetricsServer(testName);
await HelmMetalLoadBalancer.installMetalLoadBalancer(testName);
}
await new MetricsServerImpl().logMetrics(testName, PathEx.join(constants.SOLO_LOGS_DIR, `${testName}`));
}).timeout(Duration.ofMinutes(60).toMillis());
// TODO add verifications
});
})
.build();
endToEndTestSuite.runTestSuite();
export function soloOneShotDeploy(testName, deployment, minimalSetup) {
const { newArgv, argvPushGlobalFlags, optionFromFlag } = BaseCommandTest;
const argv = newArgv();
argv.push(OneShotCommandDefinition.COMMAND_NAME, OneShotCommandDefinition.SINGLE_SUBCOMMAND_NAME, OneShotCommandDefinition.SINGLE_DEPLOY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.minimalSetup), minimalSetup ? 'true' : 'false');
argvPushGlobalFlags(argv, testName);
return argv;
}
export function soloOneShotDestroy(testName) {
const { newArgv, argvPushGlobalFlags } = BaseCommandTest;
const argv = newArgv();
argv.push('one-shot', 'single', 'destroy');
argvPushGlobalFlags(argv, testName);
return argv;
}
export function soloOneShotShowDeployment(testName, deployment) {
const { newArgv, argvPushGlobalFlags, optionFromFlag } = BaseCommandTest;
const argv = newArgv();
argv.push(OneShotCommandDefinition.COMMAND_NAME, OneShotCommandDefinition.INFO_COMMAND_NAME, 'deployment');
if (deployment) {
argv.push(optionFromFlag(Flags.deployment), deployment);
}
argvPushGlobalFlags(argv, testName);
return argv;
}
export function soloDeploymentDiagnosticsLogs(testName, deployment) {
const { newArgv, argvPushGlobalFlags } = BaseCommandTest;
const argv = newArgv();
argv.push('deployment', 'diagnostics', 'logs', '--deployment', deployment);
argvPushGlobalFlags(argv, testName);
return argv;
}
//# sourceMappingURL=one-shot-single.test.js.map