diff --git a/.github/workflows/zxc-e2e-test.yaml b/.github/workflows/zxc-e2e-test.yaml index 58e6e1df5..a37d1447e 100644 --- a/.github/workflows/zxc-e2e-test.yaml +++ b/.github/workflows/zxc-e2e-test.yaml @@ -147,20 +147,20 @@ jobs: run: docker image pull kindest/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72 - name: Setup Java - if: ${{ runner.os == 'linux' && inputs.npm-test-script == 'test-e2e-node-local-build' && !cancelled() && !failure() }} + if: ${{ runner.os == 'linux' && (inputs.npm-test-script == 'test-e2e-node-local-build' || inputs.npm-test-script == 'test-e2e-node-add') && !cancelled() && !failure() }} uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version: 21.0.1 - name: Setup Gradle - if: ${{ runner.os == 'linux' && inputs.npm-test-script == 'test-e2e-node-local-build' && !cancelled() && !failure() }} + if: ${{ runner.os == 'linux' && (inputs.npm-test-script == 'test-e2e-node-local-build' || inputs.npm-test-script == 'test-e2e-node-add') && !cancelled() && !failure() }} uses: gradle/gradle-build-action@ac2d340dc04d9e1113182899e983b5400c17cda1 # v3.5.0 with: cache-read-only: false - name: Build Hedera code locally - if: ${{ runner.os == 'linux' && inputs.npm-test-script == 'test-e2e-node-local-build' && !cancelled() && !failure() }} + if: ${{ runner.os == 'linux' && (inputs.npm-test-script == 'test-e2e-node-local-build' || inputs.npm-test-script == 'test-e2e-node-add') && !cancelled() && !failure() }} run: | cd .. git clone https://github.com/hashgraph/hedera-services.git diff --git a/test/e2e/commands/node-add-local.test.mjs b/test/e2e/commands/node-add-local.test.mjs new file mode 100644 index 000000000..83df7f5f2 --- /dev/null +++ b/test/e2e/commands/node-add-local.test.mjs @@ -0,0 +1,24 @@ +/** + * 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. + * + * @jest-environment steps + */ +import { describe } from '@jest/globals' +import { testNodeAdd } from '../../test_add.mjs' + +describe('Node add with hedera local build', () => { + const localBuildPath = 'node0=../hedera-services/hedera-node/data/,../hedera-services/hedera-node/data,node2=../hedera-services/hedera-node/data' + testNodeAdd(localBuildPath) +}, 180000) diff --git a/test/e2e/commands/node-add.test.mjs b/test/e2e/commands/node-add.test.mjs index 3ba5904f5..d498348df 100644 --- a/test/e2e/commands/node-add.test.mjs +++ b/test/e2e/commands/node-add.test.mjs @@ -15,82 +15,10 @@ * * @jest-environment steps */ -import { flags } from '../../../src/commands/index.mjs' -import { constants } from '../../../src/core/index.mjs' -import { - accountCreationShouldSucceed, - balanceQueryShouldSucceed, - bootstrapNetwork, - getDefaultArgv, - getNodeIdsPrivateKeysHash, - getTmpDir, - HEDERA_PLATFORM_VERSION_TAG -} from '../../test_util.js' -import { getNodeLogs } from '../../../src/core/helpers.mjs' -import { NodeCommand } from '../../../src/commands/node.mjs' +import { describe } from '@jest/globals' +import { testNodeAdd } from '../../test_add.mjs' -describe('Node add', () => { - const defaultTimeout = 120000 - const namespace = 'node-add' - const nodeId = 'node4' - const argv = getDefaultArgv() - argv[flags.keyFormat.name] = constants.KEY_FORMAT_PEM - argv[flags.nodeIDs.name] = 'node1,node2,node3' - argv[flags.nodeID.name] = nodeId - argv[flags.generateGossipKeys.name] = true - argv[flags.generateTlsKeys.name] = true - argv[flags.keyFormat.name] = constants.KEY_FORMAT_PEM - // set the env variable SOLO_FST_CHARTS_DIR if developer wants to use local FST charts - argv[flags.chartDirectory.name] = process.env.SOLO_FST_CHARTS_DIR ? process.env.SOLO_FST_CHARTS_DIR : undefined - argv[flags.releaseTag.name] = HEDERA_PLATFORM_VERSION_TAG - argv[flags.namespace.name] = namespace - argv[flags.persistentVolumeClaims.name] = true - const bootstrapResp = bootstrapNetwork(namespace, argv) - const nodeCmd = bootstrapResp.cmd.nodeCmd - const accountCmd = bootstrapResp.cmd.accountCmd - const k8 = bootstrapResp.opts.k8 - let existingServiceMap - let existingNodeIdsPrivateKeysHash - - afterAll(async () => { - await getNodeLogs(k8, namespace) - await k8.deleteNamespace(namespace) - }, 600000) - - it('cache current version of private keys', async () => { - existingServiceMap = await nodeCmd.accountManager.getNodeServiceMap(namespace) - existingNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, constants.KEY_FORMAT_PEM, k8, getTmpDir()) - }, defaultTimeout) - - it('should succeed with init command', async () => { - const status = await accountCmd.init(argv) - expect(status).toBeTruthy() - }, 450000) - - it('should add a new node to the network successfully', async () => { - await nodeCmd.add(argv) - expect(nodeCmd.getUnusedConfigs(NodeCommand.ADD_CONFIGS_NAME)).toEqual([ - flags.app.constName, - flags.chainId.constName, - flags.devMode.constName - ]) - await nodeCmd.accountManager.close() - }, 800000) - - balanceQueryShouldSucceed(nodeCmd.accountManager, nodeCmd, namespace) - - accountCreationShouldSucceed(nodeCmd.accountManager, nodeCmd, namespace) - - it('existing nodes private keys should not have changed', async () => { - const currentNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, constants.KEY_FORMAT_PEM, k8, getTmpDir()) - - for (const [nodeId, existingKeyHashMap] of existingNodeIdsPrivateKeysHash.entries()) { - const currentNodeKeyHashMap = currentNodeIdsPrivateKeysHash.get(nodeId) - - for (const [keyFileName, existingKeyHash] of existingKeyHashMap.entries()) { - expect(`${nodeId}:${keyFileName}:${currentNodeKeyHashMap.get(keyFileName)}`).toEqual( - `${nodeId}:${keyFileName}:${existingKeyHash}`) - } - } - }, defaultTimeout) -}) +describe('Node add with released hedera', () => { + const localBuildPath = '' + testNodeAdd(localBuildPath) +}, 180000) diff --git a/test/test_add.mjs b/test/test_add.mjs new file mode 100644 index 000000000..9253215b3 --- /dev/null +++ b/test/test_add.mjs @@ -0,0 +1,108 @@ +/** + * 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. + * + * @jest-environment steps + */ +import { afterAll, describe, expect, it } from '@jest/globals' +import { + accountCreationShouldSucceed, + balanceQueryShouldSucceed, + bootstrapNetwork, + getDefaultArgv, + getNodeIdsPrivateKeysHash, + getTmpDir, + HEDERA_PLATFORM_VERSION_TAG +} from './test_util.js' +import { flags } from '../src/commands/index.mjs' +import { constants } from '../src/core/index.mjs' +import { getNodeLogs } from '../src/core/helpers.mjs' +import { NodeCommand } from '../src/commands/node.mjs' + +export function testNodeAdd (localBuildPath +) { + describe('Node add should success', () => { + const suffix = localBuildPath.substring(0, 5) + const defaultTimeout = 120000 + const namespace = 'node-add' + suffix + const nodeId = 'node4' + const argv = getDefaultArgv() + argv[flags.keyFormat.name] = constants.KEY_FORMAT_PEM + argv[flags.nodeIDs.name] = 'node1,node2,node3' + argv[flags.nodeID.name] = nodeId + argv[flags.generateGossipKeys.name] = true + argv[flags.generateTlsKeys.name] = true + argv[flags.keyFormat.name] = constants.KEY_FORMAT_PEM + // set the env variable SOLO_FST_CHARTS_DIR if developer wants to use local FST charts + argv[flags.chartDirectory.name] = process.env.SOLO_FST_CHARTS_DIR ? process.env.SOLO_FST_CHARTS_DIR : undefined + argv[flags.releaseTag.name] = HEDERA_PLATFORM_VERSION_TAG + argv[flags.namespace.name] = namespace + argv[flags.force.name] = true + argv[flags.persistentVolumeClaims.name] = true + argv[flags.localBuildPath.name] = localBuildPath + + const bootstrapResp = bootstrapNetwork(namespace, argv) + const nodeCmd = bootstrapResp.cmd.nodeCmd + const accountCmd = bootstrapResp.cmd.accountCmd + const networkCmd = bootstrapResp.cmd.networkCmd + const k8 = bootstrapResp.opts.k8 + let existingServiceMap + let existingNodeIdsPrivateKeysHash + + afterAll(async () => { + await getNodeLogs(k8, namespace) + await nodeCmd.accountManager.close() + await nodeCmd.stop(argv) + await networkCmd.destroy(argv) + await k8.deleteNamespace(namespace) + }, 600000) + + it('cache current version of private keys', async () => { + existingServiceMap = await nodeCmd.accountManager.getNodeServiceMap(namespace) + existingNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, constants.KEY_FORMAT_PEM, k8, getTmpDir()) + }, defaultTimeout) + + it('should succeed with init command', async () => { + const status = await accountCmd.init(argv) + expect(status).toBeTruthy() + }, 450000) + + it('should add a new node to the network successfully', async () => { + await nodeCmd.add(argv) + expect(nodeCmd.getUnusedConfigs(NodeCommand.ADD_CONFIGS_NAME)).toEqual([ + flags.app.constName, + flags.chainId.constName, + flags.devMode.constName + ]) + await nodeCmd.accountManager.close() + }, 800000) + + balanceQueryShouldSucceed(nodeCmd.accountManager, nodeCmd, namespace) + + accountCreationShouldSucceed(nodeCmd.accountManager, nodeCmd, namespace) + + it('existing nodes private keys should not have changed', async () => { + const currentNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, constants.KEY_FORMAT_PEM, k8, getTmpDir()) + + for (const [nodeId, existingKeyHashMap] of existingNodeIdsPrivateKeysHash.entries()) { + const currentNodeKeyHashMap = currentNodeIdsPrivateKeysHash.get(nodeId) + + for (const [keyFileName, existingKeyHash] of existingKeyHashMap.entries()) { + expect(`${nodeId}:${keyFileName}:${currentNodeKeyHashMap.get(keyFileName)}`).toEqual( + `${nodeId}:${keyFileName}:${existingKeyHash}`) + } + } + }, defaultTimeout) + }) +}