diff --git a/src/commands/cluster.mjs b/src/commands/cluster.mjs index d1e2feaea..cf2336fa2 100644 --- a/src/commands/cluster.mjs +++ b/src/commands/cluster.mjs @@ -185,6 +185,9 @@ export class ClusterCommand extends BaseCommand { } ctx.isChartInstalled = await this.chartManager.isChartInstalled(ctx.config.clusterSetupNamespace, constants.FULLSTACK_CLUSTER_SETUP_CHART) + if (!ctx.isChartInstalled) { + throw new FullstackTestingError('No chart found for the cluster') + } } }, { diff --git a/test/e2e/commands/02_account.test.mjs b/test/e2e/commands/account.test.mjs similarity index 100% rename from test/e2e/commands/02_account.test.mjs rename to test/e2e/commands/account.test.mjs diff --git a/test/e2e/commands/cluster.test.mjs b/test/e2e/commands/cluster.test.mjs new file mode 100644 index 000000000..955bca8e2 --- /dev/null +++ b/test/e2e/commands/cluster.test.mjs @@ -0,0 +1,163 @@ +/** + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the ""License""); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an ""AS IS"" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { + afterAll, + afterEach, + beforeEach, + describe, + expect, + it +} from '@jest/globals' +import { + bootstrapTestVariables, + getDefaultArgv, + TEST_CLUSTER +} from '../../test_util.js' +import { + constants +} from '../../../src/core/index.mjs' +import { flags } from '../../../src/commands/index.mjs' +import { sleep } from '../../../src/core/helpers.mjs' +import * as version from '../../../version.mjs' + +describe('ClusterCommand', () => { + const testName = 'cluster-cmd-e2e' + const namespace = testName + const argv = getDefaultArgv() + argv[flags.namespace.name] = namespace + argv[flags.releaseTag.name] = 'v0.47.0-alpha.0' + argv[flags.keyFormat.name] = constants.KEY_FORMAT_PEM + argv[flags.nodeIDs.name] = 'node0,node1,node2' + argv[flags.generateGossipKeys.name] = true + argv[flags.generateTlsKeys.name] = true + argv[flags.clusterName.name] = TEST_CLUSTER + argv[flags.fstChartVersion.name] = version.FST_CHART_VERSION + argv[flags.force.name] = true + + const bootstrapResp = bootstrapTestVariables(testName, argv) + const k8 = bootstrapResp.opts.k8 + const accountManager = bootstrapResp.opts.accountManager + const configManager = bootstrapResp.opts.configManager + const chartManager = bootstrapResp.opts.chartManager + + const clusterCmd = bootstrapResp.cmd.clusterCmd + + afterAll(async () => { + await k8.deleteNamespace(namespace) + await accountManager.close() + }) + + beforeEach(() => { + configManager.reset() + }) + + afterEach(async () => { + await sleep(5) // give a few ticks so that connections can close + }) + + it('should cleanup existing deployment', async () => { + if (await chartManager.isChartInstalled(constants.FULLSTACK_SETUP_NAMESPACE, constants.FULLSTACK_CLUSTER_SETUP_CHART)) { + expect.assertions(1) + try { + await expect(clusterCmd.reset(argv)).resolves.toBeTruthy() + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + } + }, 60000) + + it('solo cluster setup should fail with invalid cluster name', async () => { + argv[flags.clusterSetupNamespace.name] = 'INVALID' + configManager.update(argv, true) + + expect.assertions(1) + try { + await expect(clusterCmd.setup(argv)).rejects.toThrowError('Error on cluster setup') + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + + it('solo cluster setup should work with valid args', async () => { + argv[flags.clusterSetupNamespace.name] = namespace + configManager.update(argv, true) + + expect.assertions(1) + try { + await expect(clusterCmd.setup(argv)).resolves.toBeTruthy() + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + + it('function getClusterInfo should return true', async () => { + try { + await expect(clusterCmd.getClusterInfo()).resolves.toBeTruthy() + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + + it('function showClusterList should return right true', async () => { + try { + await expect(clusterCmd.showClusterList()).resolves.toBeTruthy() + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + + it('function showInstalledChartList should return right true', async () => { + try { + await expect(clusterCmd.showInstalledChartList()).resolves.toBeUndefined() + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + + // helm list would return an empty list if given invalid namespace + it('solo cluster reset should fail with invalid cluster name', async () => { + argv[flags.clusterSetupNamespace.name] = 'INVALID' + configManager.update(argv, true) + + expect.assertions(1) + try { + await expect(clusterCmd.reset(argv)).rejects.toThrowError('Error on cluster reset') + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + + it('solo cluster reset should work with valid args', async () => { + argv[flags.clusterSetupNamespace.name] = namespace + configManager.update(argv, true) + + expect.assertions(1) + try { + await expect(clusterCmd.reset(argv)).resolves.toBeTruthy() + } catch (e) { + clusterCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) +}) diff --git a/test/e2e/commands/01_node.test.mjs b/test/e2e/commands/node.test.mjs similarity index 100% rename from test/e2e/commands/01_node.test.mjs rename to test/e2e/commands/node.test.mjs diff --git a/test/e2e/core/chart_manager.test.mjs b/test/e2e/core/chart_manager.test.mjs index b3a6461aa..5761ccc92 100644 --- a/test/e2e/core/chart_manager.test.mjs +++ b/test/e2e/core/chart_manager.test.mjs @@ -36,9 +36,9 @@ describe('ChartManager', () => { }) it('should be able to check if a chart is installed', async () => { - const ns = configManager.getFlag(flags.clusterSetupNamespace) + const ns = configManager.getFlag(flags.namespace) expect(ns).not.toBeNull() - const isInstalled = await chartManager.isChartInstalled(ns, constants.FULLSTACK_CLUSTER_SETUP_CHART) + const isInstalled = await chartManager.isChartInstalled(ns, constants.FULLSTACK_DEPLOYMENT_CHART) expect(isInstalled).toBeTruthy() }) }) diff --git a/test/test_util.js b/test/test_util.js index 5282d9c8f..449c51bb5 100644 --- a/test/test_util.js +++ b/test/test_util.js @@ -33,7 +33,9 @@ import { sleep } from '../src/core/helpers.mjs' import { ChartManager, ConfigManager, - constants, Helm, K8, + constants, + Helm, + K8, KeyManager, logging, PackageDownloader, @@ -79,7 +81,7 @@ export function getDefaultArgv () { } /** - * Bootstrap network in a given namespace + * Initialize common test variables * * @param testName test name * @param argv argv for commands @@ -89,14 +91,14 @@ export function getDefaultArgv () { * @param networkCmdArg an instance of command/NetworkCommand * @param nodeCmdArg an instance of command/NodeCommand */ -export function bootstrapNetwork (testName, argv, +export function bootstrapTestVariables (testName, argv, k8Arg = null, initCmdArg = null, clusterCmdArg = null, networkCmdArg = null, nodeCmdArg = null ) { - const namespace = argv[flags.namespace.name] || 'bootstrap' + const namespace = argv[flags.namespace.name] || 'bootstrap-ns' const cacheDir = argv[flags.cacheDir.name] || getTestCacheDir(testName) const configManager = getTestConfigManager(`${testName}-solo.config`) configManager.update(argv, true) @@ -132,7 +134,8 @@ export function bootstrapNetwork (testName, argv, const clusterCmd = clusterCmdArg || new ClusterCommand(opts) const networkCmd = networkCmdArg || new NetworkCommand(opts) const nodeCmd = nodeCmdArg || new NodeCommand(opts) - const bootstrapResp = { + return { + namespace, opts, cmd: { initCmd, @@ -141,6 +144,34 @@ export function bootstrapNetwork (testName, argv, nodeCmd } } +} + +/** + * Bootstrap network in a given namespace + * + * @param testName test name + * @param argv argv for commands + * @param k8Arg an instance of core/K8 + * @param initCmdArg an instance of command/InitCommand + * @param clusterCmdArg an instance of command/ClusterCommand + * @param networkCmdArg an instance of command/NetworkCommand + * @param nodeCmdArg an instance of command/NodeCommand + */ +export function bootstrapNetwork (testName, argv, + k8Arg = null, + initCmdArg = null, + clusterCmdArg = null, + networkCmdArg = null, + nodeCmdArg = null +) { + const bootstrapResp = bootstrapTestVariables(testName, argv, k8Arg, initCmdArg, clusterCmdArg, networkCmdArg, nodeCmdArg) + const namespace = bootstrapResp.namespace + const initCmd = bootstrapResp.cmd.initCmd + const k8 = bootstrapResp.opts.k8 + const clusterCmd = bootstrapResp.cmd.clusterCmd + const networkCmd = bootstrapResp.cmd.networkCmd + const nodeCmd = bootstrapResp.cmd.nodeCmd + const chartManager = bootstrapResp.opts.chartManager describe(`Bootstrap network for test [release ${argv[flags.releaseTag.name]}, keyFormat: ${argv[flags.keyFormat.name]}]`, () => { it('should cleanup previous deployment', async () => { @@ -155,7 +186,7 @@ export function bootstrapNetwork (testName, argv, } } - if (!await k8.hasNamespace(constants.FULLSTACK_SETUP_NAMESPACE)) { + if (!await chartManager.isChartInstalled(constants.FULLSTACK_SETUP_NAMESPACE, constants.FULLSTACK_CLUSTER_SETUP_CHART)) { await clusterCmd.setup(argv) } }, 60000)