Skip to content

Commit

Permalink
feat(cli): allow user to set jvm options for Hedera nodes (#84)
Browse files Browse the repository at this point in the history
Signed-off-by: Lenin Mehedy <[email protected]>
  • Loading branch information
leninmehedy authored Feb 28, 2024
1 parent 18734f5 commit 22ff35d
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 31 deletions.
12 changes: 11 additions & 1 deletion src/commands/flags.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,15 @@ export const applicationProperties = {
}
}

export const applicationEnv = {
name: 'application-env',
definition: {
describe: 'application.env file for node',
defaultValue: '',
type: 'string'
}
}

export const apiPermissionProperties = {
name: 'api-permission-properties',
definition: {
Expand Down Expand Up @@ -454,7 +463,8 @@ export const allFlags = [
updateAccountKeys,
privateKey,
accountId,
amount
amount,
applicationEnv
]

export const allFlagsMap = new Map(allFlags.map(f => [f.name, f]))
Expand Down
41 changes: 23 additions & 18 deletions src/commands/node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export class NodeCommand extends BaseCommand {
config.releasePrefix = Templates.prepareReleasePrefix(config.releaseTag)
config.buildZipFile = `${config.cacheDir}/${config.releasePrefix}/build-${config.releaseTag}.zip`
config.keysDir = path.join(config.cacheDir, 'keys')
config.stagingDir = `${config.cacheDir}/${config.releasePrefix}/staging/${config.releaseTag}`
config.stagingDir = Templates.renderStagingDir(self.configManager, flags)
config.stagingKeysDir = path.join(config.stagingDir, 'keys')

if (config.keyFormat === constants.KEY_FORMAT_PFX && config.generateGossipKeys) {
Expand Down Expand Up @@ -227,15 +227,6 @@ export class NodeCommand extends BaseCommand {
title: 'Identify network pods',
task: (ctx, task) => self.taskCheckNetworkNodePods(ctx, task)
},
{
title: 'Fetch platform software',
task: async (ctx, _) => {
const config = ctx.config
if (config.force || !fs.existsSync(config.buildZipFile)) {
ctx.config.buildZipFile = await self.downloader.fetchPlatform(ctx.config.releaseTag, config.cacheDir)
}
}
},
{
title: 'Generate Gossip keys',
task: async (ctx, _) => {
Expand Down Expand Up @@ -349,7 +340,7 @@ export class NodeCommand extends BaseCommand {
}
},
{
title: 'Upload platform software into network nodes',
title: 'Fetch platform software into network nodes',
task:
async (ctx, task) => {
const config = ctx.config
Expand All @@ -360,7 +351,7 @@ export class NodeCommand extends BaseCommand {
subTasks.push({
title: `Node: ${chalk.yellow(nodeId)}`,
task: () =>
self.plaformInstaller.copyPlatform(podName, config.buildZipFile)
self.plaformInstaller.fetchPlatform(podName, config.releaseTag)
})
}

Expand Down Expand Up @@ -428,17 +419,21 @@ export class NodeCommand extends BaseCommand {

ctx.config = {
namespace: self.configManager.getFlag(flags.namespace),
chartDir: this.configManager.getFlag(flags.chartDirectory),
fstChartVersion: this.configManager.getFlag(flags.fstChartVersion),
chartDir: self.configManager.getFlag(flags.chartDirectory),
fstChartVersion: self.configManager.getFlag(flags.fstChartVersion),
nodeIds: helpers.parseNodeIDs(self.configManager.getFlag(flags.nodeIDs)),
deployMirrorNode: this.configManager.getFlag(flags.deployMirrorNode),
deployHederaExplorer: this.configManager.getFlag(flags.deployHederaExplorer),
updateAccountKeys: self.configManager.getFlag(flags.updateAccountKeys)
deployMirrorNode: self.configManager.getFlag(flags.deployMirrorNode),
deployHederaExplorer: self.configManager.getFlag(flags.deployHederaExplorer),
updateAccountKeys: self.configManager.getFlag(flags.updateAccountKeys),
applicationEnv: self.configManager.getFlag(flags.applicationEnv),
cacheDir: self.configManager.getFlag(flags.cacheDir)
}

ctx.config.chartPath = await this.prepareChartPath(ctx.config.chartDir,
constants.FULLSTACK_TESTING_CHART, constants.FULLSTACK_DEPLOYMENT_CHART)

ctx.config.stagingDir = Templates.renderStagingDir(self.configManager, flags)

ctx.config.valuesArg = ` --set hedera-mirror-node.enabled=${ctx.config.deployMirrorNode} --set hedera-explorer.enabled=${ctx.config.deployHederaExplorer}`

if (!await this.k8.hasNamespace(ctx.config.namespace)) {
Expand All @@ -460,6 +455,15 @@ export class NodeCommand extends BaseCommand {
title: `Start node: ${chalk.yellow(nodeId)}`,
task: async () => {
await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['rm', '-rf', `${constants.HEDERA_HAPI_PATH}/data/logs`])

// copy application.env file if required
if (ctx.config.applicationEnv) {
const stagingDir = Templates.renderStagingDir(self.configManager, flags)
const applicationEnvFile = path.join(stagingDir, 'application.env')
fs.cpSync(ctx.config.applicationEnv, applicationEnvFile)
await self.k8.copyTo(podName, constants.ROOT_CONTAINER, applicationEnvFile, `${constants.HEDERA_HAPI_PATH}`)
}

await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['systemctl', 'restart', 'network-node'])
}
})
Expand Down Expand Up @@ -818,7 +822,8 @@ export class NodeCommand extends BaseCommand {
builder: y => flags.setCommandFlags(y,
flags.namespace,
flags.nodeIDs,
flags.updateAccountKeys
flags.updateAccountKeys,
flags.applicationEnv
),
handler: argv => {
nodeCmd.logger.debug("==== Running 'node start' ===")
Expand Down
21 changes: 16 additions & 5 deletions src/core/platform_installer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,25 @@ export class PlatformInstaller {
}
}

async copyPlatform (podName, buildZipSrc) {
/**
* Fetch platform code into the container
*
* It uses curl to fetch the platform code directly inside the /home/hedera directory.
*
* @param podName pod name
* @param tag platform release tag
* @return {Promise<boolean|undefined>}
*/
async fetchPlatform (podName, tag) {
if (!podName) throw new MissingArgumentError('podName is required')
if (!buildZipSrc) throw new MissingArgumentError('buildZipSrc is required')
if (!fs.statSync(buildZipSrc).isFile()) throw new IllegalArgumentError('buildZipFile does not exists', buildZipSrc)
if (!tag) throw new MissingArgumentError('tag is required')

try {
await this.copyFiles(podName, [buildZipSrc], constants.HEDERA_USER_HOME_DIR)
return this.extractPlatform(podName, buildZipSrc)
const releaseDir = Templates.prepareReleasePrefix(tag)
const packageURL = `${constants.HEDERA_BUILDS_URL}/node/software/${releaseDir}/build-${tag}.zip`
const buildZip = path.join(constants.HEDERA_USER_HOME_DIR, `build-${tag}.zip`)
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `curl -s ${packageURL} -o ${buildZip}`)
return this.extractPlatform(podName, buildZip)
} catch (e) {
throw new FullstackTestingError(`failed to copy platform code in to pod '${podName}': ${e.message}`, e)
}
Expand Down
23 changes: 22 additions & 1 deletion src/core/templates.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*
*/
import * as x509 from '@peculiar/x509'
import { DataValidationError, MissingArgumentError } from './errors.mjs'
import path from 'path'
import { DataValidationError, IllegalArgumentError, MissingArgumentError } from './errors.mjs'

export class Templates {
static renderNetworkPodName (nodeId) {
Expand Down Expand Up @@ -116,4 +117,24 @@ export class Templates {
) {
return new x509.Name(`CN=${nodeId},ST=${state},L=${locality},O=${org},OU=${orgUnit},C=${country}`)
}

static renderStagingDir (configManager, flags) {
if (!configManager) throw new MissingArgumentError('configManager is required')
const cacheDir = configManager.getFlag(flags.cacheDir)
if (!cacheDir) {
throw new IllegalArgumentError('cacheDir cannot be empty')
}

const releaseTag = configManager.getFlag(flags.releaseTag)
if (!releaseTag) {
throw new IllegalArgumentError('releaseTag cannot be empty')
}

const releasePrefix = this.prepareReleasePrefix(releaseTag)
if (!releasePrefix) {
throw new IllegalArgumentError('releasePrefix cannot be empty')
}

return path.resolve(`${cacheDir}/${releasePrefix}/staging/${releaseTag}`)
}
}
4 changes: 1 addition & 3 deletions test/e2e/core/platform_installer_e2e.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ describe('PackageInstallerE2E', () => {
const testCacheDir = getTestCacheDir()
const podName = 'network-node0-0'
const packageVersion = 'v0.42.5'
let packageFile = ''

beforeAll(async () => {
if (!fs.existsSync(testCacheDir)) {
Expand Down Expand Up @@ -73,8 +72,7 @@ describe('PackageInstallerE2E', () => {
it('should succeed with valid tag and pod', async () => {
expect.assertions(1)
try {
packageFile = await downloader.fetchPlatform(packageVersion, testCacheDir)
await expect(installer.copyPlatform(podName, packageFile, true)).resolves.toBeTruthy()
await expect(installer.fetchPlatform(podName, packageVersion)).resolves.toBeTruthy()
const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`)
testLogger.showUser(outputs)
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions test/unit/core/platform_installer.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ describe('PackageInstaller', () => {
describe('extractPlatform', () => {
it('should fail for missing pod name', async () => {
expect.assertions(1)
await expect(installer.copyPlatform('', os.tmpdir())).rejects.toThrow(MissingArgumentError)
await expect(installer.fetchPlatform('', 'v0.42.5')).rejects.toThrow(MissingArgumentError)
})
it('should fail for missing buildZipFile path', async () => {
it('should fail for missing tag', async () => {
expect.assertions(1)
await expect(installer.copyPlatform('network-node0-0', '')).rejects.toThrow(MissingArgumentError)
await expect(installer.fetchPlatform('network-node0-0', '')).rejects.toThrow(MissingArgumentError)
})
})

Expand Down

0 comments on commit 22ff35d

Please sign in to comment.