diff --git a/.github/workflows/flow-build-application.yaml b/.github/workflows/flow-build-application.yaml index d2f0bbd98..03a37f9fc 100644 --- a/.github/workflows/flow-build-application.yaml +++ b/.github/workflows/flow-build-application.yaml @@ -90,7 +90,7 @@ jobs: coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }} coverage-report-name: ${{ needs.env-vars.outputs.e2e-mirror-node-coverage-report }} - e2e-node-tests: + e2e-node-pem-stop-add-tests: name: E2E Tests if: ${{ github.event_name == 'push' || github.event.inputs.enable-e2e-tests == 'true' }} uses: ./.github/workflows/zxc-e2e-test.yaml @@ -98,10 +98,23 @@ jobs: - env-vars - code-style with: - custom-job-label: Node - npm-test-script: test-${{ needs.env-vars.outputs.e2e-node-test-subdir }} - coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-node-test-subdir }} - coverage-report-name: ${{ needs.env-vars.outputs.e2e-node-coverage-report }} + custom-job-label: Node PEM Stop Add + npm-test-script: test-${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + coverage-report-name: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-coverage-report }} + + e2e-node-pfx-kill-add-tests: + name: E2E Tests + if: ${{ github.event_name == 'push' || github.event.inputs.enable-e2e-tests == 'true' }} + uses: ./.github/workflows/zxc-e2e-test.yaml + needs: + - env-vars + - code-style + with: + custom-job-label: Node PFX Kill Add + npm-test-script: test-${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} + coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} + coverage-report-name: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-coverage-report }} e2e-relay-tests: name: E2E Tests @@ -124,7 +137,8 @@ jobs: - unit-tests - e2e-tests - e2e-mirror-node-tests - - e2e-node-tests + - e2e-node-pem-stop-add-tests + - e2e-node-pfx-kill-add-tests - e2e-relay-tests if: ${{ (github.event_name == 'push' || github.event.inputs.enable-unit-tests == 'true' || github.event.inputs.enable-e2e-tests == 'true') && !failure() && !cancelled() }} with: @@ -135,11 +149,13 @@ jobs: enable-e2e-coverage-report: ${{ github.event_name == 'push' || github.event.inputs.enable-e2e-tests == 'true' }} e2e-test-subdir: ${{ needs.env-vars.outputs.e2e-test-subdir }} e2e-mirror-node-test-subdir: ${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }} - e2e-node-test-subdir: ${{ needs.env-vars.outputs.e2e-node-test-subdir }} + e2e-node-pem-stop-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + e2e-node-pfx-kill-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} e2e-relay-test-subdir: ${{ needs.env-vars.outputs.e2e-relay-test-subdir }} e2e-coverage-report: ${{ needs.env-vars.outputs.e2e-coverage-report }} e2e-mirror-node-coverage-report: ${{ needs.env-vars.outputs.e2e-mirror-node-coverage-report }} - e2e-node-coverage-report: ${{ needs.env-vars.outputs.e2e-node-coverage-report }} + e2e-node-pem-stop-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-coverage-report }} + e2e-node-pfx-kill-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-coverage-report }} e2e-relay-coverage-report: ${{ needs.env-vars.outputs.e2e-relay-coverage-report }} secrets: snyk-token: ${{ secrets.SNYK_TOKEN }} diff --git a/.github/workflows/flow-pull-request-checks.yaml b/.github/workflows/flow-pull-request-checks.yaml index 4c634c497..6483e1785 100644 --- a/.github/workflows/flow-pull-request-checks.yaml +++ b/.github/workflows/flow-pull-request-checks.yaml @@ -76,17 +76,29 @@ jobs: coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }} coverage-report-name: ${{ needs.env-vars.outputs.e2e-mirror-node-coverage-report }} - e2e-node-tests: + e2e-node-pem-stop-add-tests: name: E2E Tests uses: ./.github/workflows/zxc-e2e-test.yaml needs: - env-vars - code-style with: - custom-job-label: Node - npm-test-script: test-${{ needs.env-vars.outputs.e2e-node-test-subdir }} - coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-node-test-subdir }} - coverage-report-name: ${{ needs.env-vars.outputs.e2e-node-coverage-report }} + custom-job-label: Node PEM Stop Add + npm-test-script: test-${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + coverage-report-name: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-coverage-report }} + + e2e-node-pfx-kill-add-tests: + name: E2E Tests + uses: ./.github/workflows/zxc-e2e-test.yaml + needs: + - env-vars + - code-style + with: + custom-job-label: Node PFX Kill Add + npm-test-script: test-${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} + coverage-subdirectory: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} + coverage-report-name: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-coverage-report }} e2e-relay-tests: name: E2E Tests @@ -108,7 +120,8 @@ jobs: - unit-tests - e2e-tests - e2e-mirror-node-tests - - e2e-node-tests + - e2e-node-pem-stop-add-tests + - e2e-node-pfx-kill-add-tests - e2e-relay-tests if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} with: @@ -117,11 +130,13 @@ jobs: enable-e2e-coverage-report: true e2e-test-subdir: ${{ needs.env-vars.outputs.e2e-test-subdir }} e2e-mirror-node-test-subdir: ${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }} - e2e-node-test-subdir: ${{ needs.env-vars.outputs.e2e-node-test-subdir }} + e2e-node-pem-stop-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + e2e-node-pfx-kill-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} e2e-relay-test-subdir: ${{ needs.env-vars.outputs.e2e-relay-test-subdir }} e2e-coverage-report: ${{ needs.env-vars.outputs.e2e-coverage-report }} e2e-mirror-node-coverage-report: ${{ needs.env-vars.outputs.e2e-mirror-node-coverage-report }} - e2e-node-coverage-report: ${{ needs.env-vars.outputs.e2e-node-coverage-report }} + e2e-node-pem-stop-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-coverage-report }} + e2e-node-pfx-kill-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-coverage-report }} e2e-relay-coverage-report: ${{ needs.env-vars.outputs.e2e-relay-coverage-report }} secrets: codecov-token: ${{ secrets.CODECOV_TOKEN }} @@ -134,7 +149,8 @@ jobs: - unit-tests - e2e-tests - e2e-mirror-node-tests - - e2e-node-tests + - e2e-node-pem-stop-add-tests + - e2e-node-pfx-kill-add-tests - e2e-relay-tests if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} with: @@ -143,11 +159,13 @@ jobs: enable-e2e-coverage-report: true e2e-test-subdir: ${{ needs.env-vars.outputs.e2e-test-subdir }} e2e-mirror-node-test-subdir: ${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }} - e2e-node-test-subdir: ${{ needs.env-vars.outputs.e2e-node-test-subdir }} + e2e-node-pem-stop-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} + e2e-node-pfx-kill-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} e2e-relay-test-subdir: ${{ needs.env-vars.outputs.e2e-relay-test-subdir }} e2e-coverage-report: ${{ needs.env-vars.outputs.e2e-coverage-report }} e2e-mirror-node-coverage-report: ${{ needs.env-vars.outputs.e2e-mirror-node-coverage-report }} - e2e-node-coverage-report: ${{ needs.env-vars.outputs.e2e-node-coverage-report }} + e2e-node-pem-stop-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-coverage-report }} + e2e-node-pfx-kill-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-coverage-report }} e2e-relay-coverage-report: ${{ needs.env-vars.outputs.e2e-relay-coverage-report }} secrets: codacy-project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} @@ -160,7 +178,8 @@ jobs: # - unit-tests # - e2e-tests # - e2e-mirror-node-tests -# - e2e-node-tests +# - e2e-node-pem-stop-add-tests +# - e2e-node-pfx-kill-add-tests # - e2e-relay-tests # if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name && github.actor != 'dependabot[bot]' }} # with: @@ -168,11 +187,13 @@ jobs: # enable-snyk-scan: true # e2e-test-subdir: ${{ needs.env-vars.outputs.e2e-test-subdir }} # e2e-mirror-node-test-subdir: ${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }} -# e2e-node-test-subdir: ${{ needs.env-vars.outputs.e2e-node-test-subdir }} +# e2e-node-pem-stop-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-test-subdir }} +# e2e-node-pfx-kill-add-test-subdir: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-test-subdir }} # e2e-relay-test-subdir: ${{ needs.env-vars.outputs.e2e-relay-test-subdir }} # e2e-coverage-report: ${{ needs.env-vars.outputs.e2e-coverage-report }} # e2e-mirror-node-coverage-report: ${{ needs.env-vars.outputs.e2e-mirror-node-coverage-report }} -# e2e-node-coverage-report: ${{ needs.env-vars.outputs.e2e-node-coverage-report }} +# e2e-node-pem-stop-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pem-stop-add-coverage-report }} +# e2e-node-pfx-kill-add-coverage-report: ${{ needs.env-vars.outputs.e2e-node-pfx-kill-add-coverage-report }} # e2e-relay-coverage-report: ${{ needs.env-vars.outputs.e2e-relay-coverage-report }} # secrets: # snyk-token: ${{ secrets.SNYK_TOKEN }} diff --git a/.github/workflows/zxc-code-analysis.yaml b/.github/workflows/zxc-code-analysis.yaml index 46f14061e..924505b64 100644 --- a/.github/workflows/zxc-code-analysis.yaml +++ b/.github/workflows/zxc-code-analysis.yaml @@ -65,11 +65,16 @@ on: type: string required: false default: "e2e-mirror-node" - e2e-node-test-subdir: - description: "E2E Node Test Subdirectory:" + e2e-node-pem-stop-add-test-subdir: + description: "E2E Node PEM Stop Add Test Subdirectory:" type: string required: false - default: "e2e-node" + default: "e2e-node-pem-stop-add" + e2e-node-pfx-kill-add-test-subdir: + description: "E2E Node PFX Kill Add Test Subdirectory:" + type: string + required: false + default: "e2e-node-pfx-kill-add" e2e-relay-test-subdir: description: "E2E Relay Test Subdirectory:" type: string @@ -85,11 +90,16 @@ on: type: string required: false default: "E2E Mirror Node Tests Coverage Report" - e2e-node-coverage-report: - description: "E2E Node Coverage Report:" + e2e-node-pem-stop-add-coverage-report: + description: "E2E Node PEM Stop Add Coverage Report:" + type: string + required: false + default: "E2E Node PEM Stop Add Tests Coverage Report" + e2e-node-pfx-kill-add-coverage-report: + description: "E2E Node PFX Kill Add Coverage Report:" type: string required: false - default: "E2E Node Tests Coverage Report" + default: "E2E Node PFX Kill Add Tests Coverage Report" e2e-relay-coverage-report: description: "E2E Relay Coverage Report:" type: string @@ -159,12 +169,19 @@ jobs: name: ${{ inputs.e2e-mirror-node-coverage-report }} path: 'coverage/${{ inputs.e2e-mirror-node-test-subdir }}' - - name: Download E2E Node Coverage Report + - name: Download E2E Node PEM Stop Add Coverage Report + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + if: ${{ (inputs.enable-codecov-analysis || inputs.enable-codacy-coverage) && inputs.enable-e2e-coverage-report && !cancelled() && !failure() }} + with: + name: ${{ inputs.e2e-node-pem-stop-add-coverage-report }} + path: 'coverage/${{ inputs.e2e-node-pem-stop-add-test-subdir }}' + + - name: Download E2E Node PFX Kill Add Coverage Report uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 if: ${{ (inputs.enable-codecov-analysis || inputs.enable-codacy-coverage) && inputs.enable-e2e-coverage-report && !cancelled() && !failure() }} with: - name: ${{ inputs.e2e-node-coverage-report }} - path: 'coverage/${{ inputs.e2e-node-test-subdir }}' + name: ${{ inputs.e2e-node-pfx-kill-add-coverage-report }} + path: 'coverage/${{ inputs.e2e-node-pfx-kill-add-test-subdir }}' - name: Download E2E Relay Coverage Report uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 diff --git a/.github/workflows/zxc-env-vars.yaml b/.github/workflows/zxc-env-vars.yaml index 1ecbdf3cb..23146fcc2 100644 --- a/.github/workflows/zxc-env-vars.yaml +++ b/.github/workflows/zxc-env-vars.yaml @@ -32,9 +32,12 @@ on: e2e-mirror-node-test-subdir: description: "E2E Mirror Node Test Subdirectory" value: ${{ jobs.env-vars.outputs.e2e_mirror_node_test_subdir }} - e2e-node-test-subdir: - description: "E2E Node Test Subdirectory" - value: ${{ jobs.env-vars.outputs.e2e_node_test_subdir }} + e2e-node-pem-stop-add-test-subdir: + description: "E2E Node PEM Stop Add Test Subdirectory" + value: ${{ jobs.env-vars.outputs.e2e_node_pem_stop_add_test_subdir }} + e2e-node-pfx-kill-add-test-subdir: + description: "E2E Node PFX Kill Add Test Subdirectory" + value: ${{ jobs.env-vars.outputs.e2e_node_pfx_kill_add_test_subdir }} e2e-relay-test-subdir: description: "E2E Relay Test Subdirectory" value: ${{ jobs.env-vars.outputs.e2e_relay_test_subdir }} @@ -44,9 +47,12 @@ on: e2e-mirror-node-coverage-report: description: "E2E Mirror Node Tests Coverage Report" value: ${{ jobs.env-vars.outputs.e2e_mirror_node_coverage_report }} - e2e-node-coverage-report: - description: "E2E Node Tests Coverage Report" - value: ${{ jobs.env-vars.outputs.e2e_node_coverage_report }} + e2e-node-pem-stop-add-coverage-report: + description: "E2E Node PEM Stop Add Tests Coverage Report" + value: ${{ jobs.env-vars.outputs.e2e_node_pem_stop_add_coverage_report }} + e2e-node-pfx-kill-add-coverage-report: + description: "E2E Node PFX Kill Add Tests Coverage Report" + value: ${{ jobs.env-vars.outputs.e2e_node_pfx_kill_add_coverage_report }} e2e-relay-coverage-report: description: "E2E Relay Tests Coverage Report" value: ${{ jobs.env-vars.outputs.e2e_relay_coverage_report }} @@ -62,11 +68,13 @@ jobs: outputs: e2e_test_subdir: e2e e2e_mirror_node_test_subdir: e2e-mirror-node - e2e_node_test_subdir: e2e-node + e2e_node_pem_stop_add_test_subdir: e2e-node-pem-stop-add + e2e_node_pfx_kill_add_test_subdir: e2e-node-pfx-kill-add e2e_relay_test_subdir: e2e-relay e2e_coverage_report: "E2E Tests Coverage Report" e2e_mirror_node_coverage_report: "E2E Mirror Node Tests Coverage Report" - e2e_node_coverage_report: "E2E Node Tests Coverage Report" + e2e_node_pem_stop_add_coverage_report: "E2E Node PEM Stop Add Tests Coverage Report" + e2e_node_pfx_kill_add_coverage_report: "E2E Node PFX Kill Add Tests Coverage Report" e2e_relay_coverage_report: "E2E Relay Tests Coverage Report" steps: - run: echo "Exposing environment variables to reusable workflows" diff --git a/package.json b/package.json index db6ef1cb0..86a64c6d7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "test-e2e-all": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E All Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e' --testPathIgnorePatterns=\".*/unit/.*\"", "test-e2e": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e' --testPathIgnorePatterns=\".*/unit/.*\" --testPathIgnorePatterns=\".*/e2e/commands/mirror_node.*\" --testPathIgnorePatterns=\".*/e2e/commands/node.*\" --testPathIgnorePatterns=\".*/e2e/commands/relay.*\"", "test-e2e-mirror-node": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E Mirror Node Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e-mirror-node.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e-mirror-node' --testRegex=\".*\\/e2e\\/commands\\/mirror_node\\.test\\.mjs\"", - "test-e2e-node": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E Node Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e-node.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e-node' --testRegex=\".*\\/e2e\\/commands\\/node\\.test\\.mjs\"", + "test-e2e-node-pem-stop-add": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E Node PEM Stop Add Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e-node-pem-stop-add.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e-node-pem-stop-add' --testRegex=\".*\\/e2e\\/commands\\/node_pem_stop_add\\.test\\.mjs\"", + "test-e2e-node-pfx-kill-add": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E Node PFX Kill Add Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e-node-pfx-kill-add.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e-node-pfx-kill-add' --testRegex=\".*\\/e2e\\/commands\\/node_pfx_kill_add\\.test\\.mjs\"", "test-e2e-relay": "NODE_OPTIONS=--experimental-vm-modules JEST_SUITE_NAME='Jest E2E Relay Tests' JEST_JUNIT_OUTPUT_NAME='junit-e2e-relay.xml' jest --runInBand --detectOpenHandles --forceExit --coverage --coverageDirectory='coverage/e2e-relay' --testRegex=\".*\\/e2e\\/commands\\/relay\\.test\\.mjs\"", "merge-clean": "rm -rf .nyc_output && mkdir .nyc_output && rm -rf coverage/lcov-report && rm -rf coverage/solo && rm coverage/*.*", "merge-e2e": "nyc merge ./coverage/e2e/ .nyc_output/coverage.json", diff --git a/test/e2e/commands/node.test.mjs b/test/e2e/commands/node.test.mjs deleted file mode 100644 index 1de956404..000000000 --- a/test/e2e/commands/node.test.mjs +++ /dev/null @@ -1,335 +0,0 @@ -/** - * 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 { - AccountBalanceQuery, - AccountCreateTransaction, - Hbar, - HbarUnit, - PrivateKey -} from '@hashgraph/sdk' -import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it -} from '@jest/globals' -import { flags } from '../../../src/commands/index.mjs' -import { - constants, Templates -} from '../../../src/core/index.mjs' -import { - bootstrapNetwork, - getDefaultArgv, - getTestConfigManager, getTmpDir, - TEST_CLUSTER -} from '../../test_util.js' -import { sleep } from '../../../src/core/helpers.mjs' -import path from 'path' -import fs from 'fs' -import crypto from 'crypto' - -const defaultTimeout = 20000 - -describe.each([ - { releaseTag: 'v0.49.0-alpha.2', keyFormat: constants.KEY_FORMAT_PFX, testName: 'node-cmd-e2e-pfx', mode: 'kill' }, - { releaseTag: 'v0.49.0-alpha.2', keyFormat: constants.KEY_FORMAT_PEM, testName: 'node-cmd-e2e-pem', mode: 'stop' } -])('NodeCommand', (input) => { - const testName = input.testName - const namespace = testName - const argv = getDefaultArgv() - argv[flags.namespace.name] = namespace - argv[flags.releaseTag.name] = input.releaseTag - argv[flags.keyFormat.name] = input.keyFormat - argv[flags.nodeIDs.name] = 'node0,node1,node2,node3' - argv[flags.generateGossipKeys.name] = true - argv[flags.generateTlsKeys.name] = true - argv[flags.clusterName.name] = TEST_CLUSTER - const bootstrapResp = bootstrapNetwork(testName, argv) - const accountManager = bootstrapResp.opts.accountManager - const k8 = bootstrapResp.opts.k8 - const nodeCmd = bootstrapResp.cmd.nodeCmd - - afterEach(async () => { - await nodeCmd.close() - await accountManager.close() - }, 120000) - - afterAll(async () => { - await k8.deleteNamespace(namespace) - }, 120000) - - describe(`Node should have started successfully [mode ${input.mode}, release ${input.releaseTag}, keyFormat: ${input.keyFormat}]`, () => { - balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) - - accountCreationShouldSucceed(accountManager, nodeCmd, namespace) - - it(`Node Proxy should be UP [mode ${input.mode}, release ${input.releaseTag}, keyFormat: ${input.keyFormat}`, async () => { - expect.assertions(1) - - try { - await expect(nodeCmd.checkNetworkNodeProxyUp('node0', 30499)).resolves.toBeTruthy() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - await nodeCmd.close() - } - }, defaultTimeout) - }) - - describe(`Node should refresh successfully [mode ${input.mode}, release ${input.releaseTag}, keyFormat: ${input.keyFormat}]`, () => { - const nodeId = 'node0' - - beforeAll(async () => { - const podName = await nodeRefreshTestSetup(argv, testName, k8, nodeId) - if (input.mode === 'kill') { - const resp = await k8.kubeClient.deleteNamespacedPod(podName, namespace) - expect(resp.response.statusCode).toEqual(200) - await sleep(20000) // sleep to wait for pod to finish terminating - } else if (input.mode === 'stop') { - await expect(nodeCmd.stop(argv)).resolves.toBeTruthy() - await sleep(20000) // give time for node to stop and update its logs - } else { - throw new Error(`invalid mode: ${input.mode}`) - } - }, 120000) - - nodePodShouldBeRunning(nodeCmd, namespace, nodeId) - - nodeShouldNotBeActive(nodeCmd, nodeId) - - nodeRefreshShouldSucceed(nodeId, nodeCmd, argv) - - balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) - - accountCreationShouldSucceed(accountManager, nodeCmd, namespace) - }) - - describe(`Should add a new node to the network [release ${input.releaseTag}, keyFormat: ${input.keyFormat}]`, () => { - const nodeId = 'node4' - let existingServiceMap - let existingNodeIdsPrivateKeysHash - - beforeAll(async () => { - argv[flags.nodeIDs.name] = nodeId - const configManager = getTestConfigManager(`${testName}-solo.config`) - configManager.update(argv, true) - existingServiceMap = await accountManager.getNodeServiceMap(namespace) - existingNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, input.keyFormat, k8, getTmpDir()) - }) - - it(`${nodeId} should not exist`, async () => { - try { - await expect(nodeCmd.checkNetworkNodePod(namespace, nodeId, 10, 50)).rejects.toThrowError(`no pod found for nodeId: ${nodeId}`) - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - await nodeCmd.close() - } - }, 120000) - - balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) - - accountCreationShouldSucceed(accountManager, nodeCmd, namespace) - - it(`add ${nodeId} to the network`, async () => { - try { - await expect(nodeCmd.add(argv)).resolves.toBeTruthy() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - await nodeCmd.close() - await sleep(10000) // sleep to wait for node to finish starting - } - }, 240000) - - balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) - - accountCreationShouldSucceed(accountManager, nodeCmd, namespace) - - it('existing nodes private keys should not have changed', async () => { - const currentNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, input.keyFormat, 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}`) - } - } - }, 60000) - }) -}) - -function accountCreationShouldSucceed (accountManager, nodeCmd, namespace) { - it('Account creation should succeed', async () => { - expect.assertions(3) - - try { - await accountManager.loadNodeClient(namespace) - expect(accountManager._nodeClient).not.toBeNull() - const privateKey = PrivateKey.generate() - const amount = 100 - - const newAccount = await new AccountCreateTransaction() - .setKey(privateKey) - .setInitialBalance(Hbar.from(amount, HbarUnit.Hbar)) - .execute(accountManager._nodeClient) - - // Get the new account ID - const getReceipt = await newAccount.getReceipt(accountManager._nodeClient) - const accountInfo = { - accountId: getReceipt.accountId.toString(), - privateKey: privateKey.toString(), - publicKey: privateKey.publicKey.toString(), - balance: amount - } - - expect(accountInfo.accountId).not.toBeNull() - expect(accountInfo.balance).toEqual(amount) - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } - }, 60000) -} - -function balanceQueryShouldSucceed (accountManager, nodeCmd, namespace) { - it('Balance query should succeed', async () => { - expect.assertions(3) - - try { - expect(accountManager._nodeClient).toBeNull() - await accountManager.loadNodeClient(namespace) - expect(accountManager._nodeClient).not.toBeNull() - - const balance = await new AccountBalanceQuery() - .setAccountId(accountManager._nodeClient.getOperator().accountId) - .execute(accountManager._nodeClient) - - expect(balance.hbars).not.toBeNull() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } - await sleep(1000) - }, 120000) -} - -function nodePodShouldBeRunning (nodeCmd, namespace, nodeId) { - it(`${nodeId} should be running`, async () => { - try { - await expect(nodeCmd.checkNetworkNodePod(namespace, nodeId)).resolves.toBeTruthy() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - await nodeCmd.close() - } - }, defaultTimeout) -} - -function nodeRefreshShouldSucceed (nodeId, nodeCmd, argv) { - it(`${nodeId} refresh should succeed`, async () => { - try { - await expect(nodeCmd.refresh(argv)).resolves.toBeTruthy() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - await nodeCmd.close() - await sleep(10000) // sleep to wait for node to finish starting - } - }, 1200000) -} - -function nodeShouldNotBeActive (nodeCmd, nodeId) { - it(`${nodeId} should not be ACTIVE`, async () => { - expect(2) - try { - await expect(nodeCmd.checkNetworkNodeState(nodeId, 5)).rejects.toThrowError() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).not.toBeNull() - } finally { - await nodeCmd.close() - } - }, defaultTimeout) -} - -async function nodeRefreshTestSetup (argv, testName, k8, nodeId) { - argv[flags.nodeIDs.name] = nodeId - const configManager = getTestConfigManager(`${testName}-solo.config`) - configManager.update(argv, true) - - const podArray = await k8.getPodsByLabel( - [`app=network-${nodeId}`, 'fullstack.hedera.com/type=network-node']) - - if (podArray.length > 0) { - const podName = podArray[0].metadata.name - k8.logger.info(`nodeRefreshTestSetup: podName: ${podName}`) - return podName - } else { - throw new Error(`pod for ${nodeId} not found`) - } -} - -async function getNodeIdsPrivateKeysHash (existingServiceMap, namespace, keyFormat, k8, destDir) { - const dataKeysDir = `${constants.HEDERA_HAPI_PATH}/data/keys` - const tlsKeysDir = constants.HEDERA_HAPI_PATH - const nodeKeyHashMap = new Map() - for (const serviceObject of existingServiceMap.values()) { - const keyHashMap = new Map() - const nodeId = serviceObject.node - const uniqueNodeDestDir = path.join(destDir, nodeId) - if (!fs.existsSync(uniqueNodeDestDir)) { - fs.mkdirSync(uniqueNodeDestDir, { recursive: true }) - } - switch (keyFormat) { - case constants.KEY_FORMAT_PFX: - await addKeyHashToMap(k8, nodeId, dataKeysDir, uniqueNodeDestDir, keyHashMap, Templates.renderGossipPfxPrivateKeyFile(nodeId)) - break - case constants.KEY_FORMAT_PEM: - await addKeyHashToMap(k8, nodeId, dataKeysDir, uniqueNodeDestDir, keyHashMap, Templates.renderGossipPemPrivateKeyFile(constants.SIGNING_KEY_PREFIX, nodeId)) - await addKeyHashToMap(k8, nodeId, dataKeysDir, uniqueNodeDestDir, keyHashMap, Templates.renderGossipPemPrivateKeyFile(constants.AGREEMENT_KEY_PREFIX, nodeId)) - break - default: - throw new Error(`invalid keyFormat: ${keyFormat}`) - } - await addKeyHashToMap(k8, nodeId, tlsKeysDir, uniqueNodeDestDir, keyHashMap, 'hedera.key') - nodeKeyHashMap.set(nodeId, keyHashMap) - } - return nodeKeyHashMap -} - -async function addKeyHashToMap (k8, nodeId, keyDir, uniqueNodeDestDir, keyHashMap, privateKeyFileName) { - await k8.copyFrom( - Templates.renderNetworkPodName(nodeId), - 'root-container', - path.join(keyDir, privateKeyFileName), - uniqueNodeDestDir) - const keyBytes = await fs.readFileSync(path.join(uniqueNodeDestDir, privateKeyFileName)) - const keyString = keyBytes.toString() - keyHashMap.set(privateKeyFileName, crypto.createHash('sha256').update(keyString).digest('base64')) -} diff --git a/test/e2e/commands/node_pem_stop_add.test.mjs b/test/e2e/commands/node_pem_stop_add.test.mjs new file mode 100644 index 000000000..d65d65d6a --- /dev/null +++ b/test/e2e/commands/node_pem_stop_add.test.mjs @@ -0,0 +1,25 @@ +/** + * 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 { constants } from '../../../src/core/index.mjs' +import { e2eNodeKeyRefreshAddTest } from '../e2e_node_util.js' + +describe('NodeCommand', () => { + e2eNodeKeyRefreshAddTest(constants.KEY_FORMAT_PEM, 'node-cmd-e2e-pem', 'stop') +}) diff --git a/test/e2e/commands/node_pfx_kill_add.test.mjs b/test/e2e/commands/node_pfx_kill_add.test.mjs new file mode 100644 index 000000000..912b63521 --- /dev/null +++ b/test/e2e/commands/node_pfx_kill_add.test.mjs @@ -0,0 +1,25 @@ +/** + * 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 { constants } from '../../../src/core/index.mjs' +import { e2eNodeKeyRefreshAddTest } from '../e2e_node_util.js' + +describe('NodeCommand', () => { + e2eNodeKeyRefreshAddTest(constants.KEY_FORMAT_PFX, 'node-cmd-e2e-pfx', 'kill') +}) diff --git a/test/e2e/e2e_node_util.js b/test/e2e/e2e_node_util.js new file mode 100644 index 000000000..4785c4fa0 --- /dev/null +++ b/test/e2e/e2e_node_util.js @@ -0,0 +1,333 @@ +/** + * 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 { + AccountBalanceQuery, + AccountCreateTransaction, + Hbar, + HbarUnit, + PrivateKey +} from '@hashgraph/sdk' +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it +} from '@jest/globals' +import { flags } from '../../src/commands/index.mjs' +import { + constants, Templates +} from '../../src/core/index.mjs' +import { + bootstrapNetwork, + getDefaultArgv, + getTestConfigManager, getTmpDir, + TEST_CLUSTER +} from '../test_util.js' +import { sleep } from '../../src/core/helpers.mjs' +import path from 'path' +import fs from 'fs' +import crypto from 'crypto' + +export function e2eNodeKeyRefreshAddTest (keyFormat, testName, mode, releaseTag = 'v0.49.0-alpha.2') { + const defaultTimeout = 20000 + + describe(`NodeCommand [testName ${testName}, mode ${mode}, keyFormat: ${keyFormat}, release ${releaseTag}]`, () => { + const namespace = testName + const argv = getDefaultArgv() + argv[flags.namespace.name] = namespace + argv[flags.releaseTag.name] = releaseTag + argv[flags.keyFormat.name] = keyFormat + argv[flags.nodeIDs.name] = 'node0,node1,node2,node3' + argv[flags.generateGossipKeys.name] = true + argv[flags.generateTlsKeys.name] = true + argv[flags.clusterName.name] = TEST_CLUSTER + const bootstrapResp = bootstrapNetwork(testName, argv) + const accountManager = bootstrapResp.opts.accountManager + const k8 = bootstrapResp.opts.k8 + const nodeCmd = bootstrapResp.cmd.nodeCmd + + afterEach(async () => { + await nodeCmd.close() + await accountManager.close() + }, 120000) + + afterAll(async () => { + await k8.deleteNamespace(namespace) + }, 120000) + + describe(`Node should have started successfully [mode ${mode}, release ${releaseTag}, keyFormat: ${keyFormat}]`, () => { + balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) + + accountCreationShouldSucceed(accountManager, nodeCmd, namespace) + + it(`Node Proxy should be UP [mode ${mode}, release ${releaseTag}, keyFormat: ${keyFormat}`, async () => { + expect.assertions(1) + + try { + await expect(nodeCmd.checkNetworkNodeProxyUp('node0', 30499)).resolves.toBeTruthy() + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } finally { + await nodeCmd.close() + } + }, defaultTimeout) + }) + + describe(`Node should refresh successfully [mode ${mode}, release ${releaseTag}, keyFormat: ${keyFormat}]`, () => { + const nodeId = 'node0' + + beforeAll(async () => { + const podName = await nodeRefreshTestSetup(argv, testName, k8, nodeId) + if (mode === 'kill') { + const resp = await k8.kubeClient.deleteNamespacedPod(podName, namespace) + expect(resp.response.statusCode).toEqual(200) + await sleep(20000) // sleep to wait for pod to finish terminating + } else if (mode === 'stop') { + await expect(nodeCmd.stop(argv)).resolves.toBeTruthy() + await sleep(20000) // give time for node to stop and update its logs + } else { + throw new Error(`invalid mode: ${mode}`) + } + }, 120000) + + nodePodShouldBeRunning(nodeCmd, namespace, nodeId) + + nodeShouldNotBeActive(nodeCmd, nodeId) + + nodeRefreshShouldSucceed(nodeId, nodeCmd, argv) + + balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) + + accountCreationShouldSucceed(accountManager, nodeCmd, namespace) + }) + + describe(`Should add a new node to the network [release ${releaseTag}, keyFormat: ${keyFormat}]`, () => { + const nodeId = 'node4' + let existingServiceMap + let existingNodeIdsPrivateKeysHash + + beforeAll(async () => { + argv[flags.nodeIDs.name] = nodeId + const configManager = getTestConfigManager(`${testName}-solo.config`) + configManager.update(argv, true) + existingServiceMap = await accountManager.getNodeServiceMap(namespace) + existingNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, keyFormat, k8, getTmpDir()) + }, defaultTimeout) + + it(`${nodeId} should not exist`, async () => { + try { + await expect(nodeCmd.checkNetworkNodePod(namespace, nodeId, 10, 50)).rejects.toThrowError(`no pod found for nodeId: ${nodeId}`) + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } finally { + await nodeCmd.close() + } + }, 120000) + + balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) + + accountCreationShouldSucceed(accountManager, nodeCmd, namespace) + + it(`add ${nodeId} to the network`, async () => { + try { + await expect(nodeCmd.add(argv)).resolves.toBeTruthy() + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } finally { + await nodeCmd.close() + await sleep(10000) // sleep to wait for node to finish starting + } + }, 240000) + + balanceQueryShouldSucceed(accountManager, nodeCmd, namespace) + + accountCreationShouldSucceed(accountManager, nodeCmd, namespace) + + it('existing nodes private keys should not have changed', async () => { + const currentNodeIdsPrivateKeysHash = await getNodeIdsPrivateKeysHash(existingServiceMap, namespace, keyFormat, 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}`) + } + } + }, 60000) + }) + }) + + function accountCreationShouldSucceed (accountManager, nodeCmd, namespace) { + it('Account creation should succeed', async () => { + expect.assertions(3) + + try { + await accountManager.loadNodeClient(namespace) + expect(accountManager._nodeClient).not.toBeNull() + const privateKey = PrivateKey.generate() + const amount = 100 + + const newAccount = await new AccountCreateTransaction() + .setKey(privateKey) + .setInitialBalance(Hbar.from(amount, HbarUnit.Hbar)) + .execute(accountManager._nodeClient) + + // Get the new account ID + const getReceipt = await newAccount.getReceipt(accountManager._nodeClient) + const accountInfo = { + accountId: getReceipt.accountId.toString(), + privateKey: privateKey.toString(), + publicKey: privateKey.publicKey.toString(), + balance: amount + } + + expect(accountInfo.accountId).not.toBeNull() + expect(accountInfo.balance).toEqual(amount) + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } + }, 60000) + } + + function balanceQueryShouldSucceed (accountManager, nodeCmd, namespace) { + it('Balance query should succeed', async () => { + expect.assertions(3) + + try { + expect(accountManager._nodeClient).toBeNull() + await accountManager.loadNodeClient(namespace) + expect(accountManager._nodeClient).not.toBeNull() + + const balance = await new AccountBalanceQuery() + .setAccountId(accountManager._nodeClient.getOperator().accountId) + .execute(accountManager._nodeClient) + + expect(balance.hbars).not.toBeNull() + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } + await sleep(1000) + }, 120000) + } + + function nodePodShouldBeRunning (nodeCmd, namespace, nodeId) { + it(`${nodeId} should be running`, async () => { + try { + await expect(nodeCmd.checkNetworkNodePod(namespace, nodeId)).resolves.toBeTruthy() + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } finally { + await nodeCmd.close() + } + }, defaultTimeout) + } + + function nodeRefreshShouldSucceed (nodeId, nodeCmd, argv) { + it(`${nodeId} refresh should succeed`, async () => { + try { + await expect(nodeCmd.refresh(argv)).resolves.toBeTruthy() + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).toBeNull() + } finally { + await nodeCmd.close() + await sleep(10000) // sleep to wait for node to finish starting + } + }, 1200000) + } + + function nodeShouldNotBeActive (nodeCmd, nodeId) { + it(`${nodeId} should not be ACTIVE`, async () => { + expect(2) + try { + await expect(nodeCmd.checkNetworkNodeState(nodeId, 5)).rejects.toThrowError() + } catch (e) { + nodeCmd.logger.showUserError(e) + expect(e).not.toBeNull() + } finally { + await nodeCmd.close() + } + }, defaultTimeout) + } + + async function nodeRefreshTestSetup (argv, testName, k8, nodeId) { + argv[flags.nodeIDs.name] = nodeId + const configManager = getTestConfigManager(`${testName}-solo.config`) + configManager.update(argv, true) + + const podArray = await k8.getPodsByLabel( + [`app=network-${nodeId}`, 'fullstack.hedera.com/type=network-node']) + + if (podArray.length > 0) { + const podName = podArray[0].metadata.name + k8.logger.info(`nodeRefreshTestSetup: podName: ${podName}`) + return podName + } else { + throw new Error(`pod for ${nodeId} not found`) + } + } + + async function getNodeIdsPrivateKeysHash (existingServiceMap, namespace, keyFormat, k8, destDir) { + const dataKeysDir = `${constants.HEDERA_HAPI_PATH}/data/keys` + const tlsKeysDir = constants.HEDERA_HAPI_PATH + const nodeKeyHashMap = new Map() + for (const serviceObject of existingServiceMap.values()) { + const keyHashMap = new Map() + const nodeId = serviceObject.node + const uniqueNodeDestDir = path.join(destDir, nodeId) + if (!fs.existsSync(uniqueNodeDestDir)) { + fs.mkdirSync(uniqueNodeDestDir, { recursive: true }) + } + switch (keyFormat) { + case constants.KEY_FORMAT_PFX: + await addKeyHashToMap(k8, nodeId, dataKeysDir, uniqueNodeDestDir, keyHashMap, Templates.renderGossipPfxPrivateKeyFile(nodeId)) + break + case constants.KEY_FORMAT_PEM: + await addKeyHashToMap(k8, nodeId, dataKeysDir, uniqueNodeDestDir, keyHashMap, Templates.renderGossipPemPrivateKeyFile(constants.SIGNING_KEY_PREFIX, nodeId)) + await addKeyHashToMap(k8, nodeId, dataKeysDir, uniqueNodeDestDir, keyHashMap, Templates.renderGossipPemPrivateKeyFile(constants.AGREEMENT_KEY_PREFIX, nodeId)) + break + default: + throw new Error(`invalid keyFormat: ${keyFormat}`) + } + await addKeyHashToMap(k8, nodeId, tlsKeysDir, uniqueNodeDestDir, keyHashMap, 'hedera.key') + nodeKeyHashMap.set(nodeId, keyHashMap) + } + return nodeKeyHashMap + } + + async function addKeyHashToMap (k8, nodeId, keyDir, uniqueNodeDestDir, keyHashMap, privateKeyFileName) { + await k8.copyFrom( + Templates.renderNetworkPodName(nodeId), + 'root-container', + path.join(keyDir, privateKeyFileName), + uniqueNodeDestDir) + const keyBytes = await fs.readFileSync(path.join(uniqueNodeDestDir, privateKeyFileName)) + const keyString = keyBytes.toString() + keyHashMap.set(privateKeyFileName, crypto.createHash('sha256').update(keyString).digest('base64')) + } +}