Skip to content

Commit

Permalink
feat: add local build support for node add command (#509)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeffrey Tang <jeffrey@swirldslabs.com>
  • Loading branch information
JeffreyDallas authored Aug 30, 2024
1 parent b7c07d9 commit a7e778f
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 81 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/zxc-e2e-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions test/e2e/commands/node-add-local.test.mjs
Original file line number Diff line number Diff line change
@@ -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)
84 changes: 6 additions & 78 deletions test/e2e/commands/node-add.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
108 changes: 108 additions & 0 deletions test/test_add.mjs
Original file line number Diff line number Diff line change
@@ -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)
})
}

0 comments on commit a7e778f

Please sign in to comment.