Skip to content

Commit 22ff35d

Browse files
authored
feat(cli): allow user to set jvm options for Hedera nodes (#84)
Signed-off-by: Lenin Mehedy <[email protected]>
1 parent 18734f5 commit 22ff35d

File tree

6 files changed

+76
-31
lines changed

6 files changed

+76
-31
lines changed

src/commands/flags.mjs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,15 @@ export const applicationProperties = {
342342
}
343343
}
344344

345+
export const applicationEnv = {
346+
name: 'application-env',
347+
definition: {
348+
describe: 'application.env file for node',
349+
defaultValue: '',
350+
type: 'string'
351+
}
352+
}
353+
345354
export const apiPermissionProperties = {
346355
name: 'api-permission-properties',
347356
definition: {
@@ -454,7 +463,8 @@ export const allFlags = [
454463
updateAccountKeys,
455464
privateKey,
456465
accountId,
457-
amount
466+
amount,
467+
applicationEnv
458468
]
459469

460470
export const allFlagsMap = new Map(allFlags.map(f => [f.name, f]))

src/commands/node.mjs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export class NodeCommand extends BaseCommand {
194194
config.releasePrefix = Templates.prepareReleasePrefix(config.releaseTag)
195195
config.buildZipFile = `${config.cacheDir}/${config.releasePrefix}/build-${config.releaseTag}.zip`
196196
config.keysDir = path.join(config.cacheDir, 'keys')
197-
config.stagingDir = `${config.cacheDir}/${config.releasePrefix}/staging/${config.releaseTag}`
197+
config.stagingDir = Templates.renderStagingDir(self.configManager, flags)
198198
config.stagingKeysDir = path.join(config.stagingDir, 'keys')
199199

200200
if (config.keyFormat === constants.KEY_FORMAT_PFX && config.generateGossipKeys) {
@@ -227,15 +227,6 @@ export class NodeCommand extends BaseCommand {
227227
title: 'Identify network pods',
228228
task: (ctx, task) => self.taskCheckNetworkNodePods(ctx, task)
229229
},
230-
{
231-
title: 'Fetch platform software',
232-
task: async (ctx, _) => {
233-
const config = ctx.config
234-
if (config.force || !fs.existsSync(config.buildZipFile)) {
235-
ctx.config.buildZipFile = await self.downloader.fetchPlatform(ctx.config.releaseTag, config.cacheDir)
236-
}
237-
}
238-
},
239230
{
240231
title: 'Generate Gossip keys',
241232
task: async (ctx, _) => {
@@ -349,7 +340,7 @@ export class NodeCommand extends BaseCommand {
349340
}
350341
},
351342
{
352-
title: 'Upload platform software into network nodes',
343+
title: 'Fetch platform software into network nodes',
353344
task:
354345
async (ctx, task) => {
355346
const config = ctx.config
@@ -360,7 +351,7 @@ export class NodeCommand extends BaseCommand {
360351
subTasks.push({
361352
title: `Node: ${chalk.yellow(nodeId)}`,
362353
task: () =>
363-
self.plaformInstaller.copyPlatform(podName, config.buildZipFile)
354+
self.plaformInstaller.fetchPlatform(podName, config.releaseTag)
364355
})
365356
}
366357

@@ -428,17 +419,21 @@ export class NodeCommand extends BaseCommand {
428419

429420
ctx.config = {
430421
namespace: self.configManager.getFlag(flags.namespace),
431-
chartDir: this.configManager.getFlag(flags.chartDirectory),
432-
fstChartVersion: this.configManager.getFlag(flags.fstChartVersion),
422+
chartDir: self.configManager.getFlag(flags.chartDirectory),
423+
fstChartVersion: self.configManager.getFlag(flags.fstChartVersion),
433424
nodeIds: helpers.parseNodeIDs(self.configManager.getFlag(flags.nodeIDs)),
434-
deployMirrorNode: this.configManager.getFlag(flags.deployMirrorNode),
435-
deployHederaExplorer: this.configManager.getFlag(flags.deployHederaExplorer),
436-
updateAccountKeys: self.configManager.getFlag(flags.updateAccountKeys)
425+
deployMirrorNode: self.configManager.getFlag(flags.deployMirrorNode),
426+
deployHederaExplorer: self.configManager.getFlag(flags.deployHederaExplorer),
427+
updateAccountKeys: self.configManager.getFlag(flags.updateAccountKeys),
428+
applicationEnv: self.configManager.getFlag(flags.applicationEnv),
429+
cacheDir: self.configManager.getFlag(flags.cacheDir)
437430
}
438431

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

435+
ctx.config.stagingDir = Templates.renderStagingDir(self.configManager, flags)
436+
442437
ctx.config.valuesArg = ` --set hedera-mirror-node.enabled=${ctx.config.deployMirrorNode} --set hedera-explorer.enabled=${ctx.config.deployHederaExplorer}`
443438

444439
if (!await this.k8.hasNamespace(ctx.config.namespace)) {
@@ -460,6 +455,15 @@ export class NodeCommand extends BaseCommand {
460455
title: `Start node: ${chalk.yellow(nodeId)}`,
461456
task: async () => {
462457
await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['rm', '-rf', `${constants.HEDERA_HAPI_PATH}/data/logs`])
458+
459+
// copy application.env file if required
460+
if (ctx.config.applicationEnv) {
461+
const stagingDir = Templates.renderStagingDir(self.configManager, flags)
462+
const applicationEnvFile = path.join(stagingDir, 'application.env')
463+
fs.cpSync(ctx.config.applicationEnv, applicationEnvFile)
464+
await self.k8.copyTo(podName, constants.ROOT_CONTAINER, applicationEnvFile, `${constants.HEDERA_HAPI_PATH}`)
465+
}
466+
463467
await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['systemctl', 'restart', 'network-node'])
464468
}
465469
})
@@ -818,7 +822,8 @@ export class NodeCommand extends BaseCommand {
818822
builder: y => flags.setCommandFlags(y,
819823
flags.namespace,
820824
flags.nodeIDs,
821-
flags.updateAccountKeys
825+
flags.updateAccountKeys,
826+
flags.applicationEnv
822827
),
823828
handler: argv => {
824829
nodeCmd.logger.debug("==== Running 'node start' ===")

src/core/platform_installer.mjs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,25 @@ export class PlatformInstaller {
9999
}
100100
}
101101

102-
async copyPlatform (podName, buildZipSrc) {
102+
/**
103+
* Fetch platform code into the container
104+
*
105+
* It uses curl to fetch the platform code directly inside the /home/hedera directory.
106+
*
107+
* @param podName pod name
108+
* @param tag platform release tag
109+
* @return {Promise<boolean|undefined>}
110+
*/
111+
async fetchPlatform (podName, tag) {
103112
if (!podName) throw new MissingArgumentError('podName is required')
104-
if (!buildZipSrc) throw new MissingArgumentError('buildZipSrc is required')
105-
if (!fs.statSync(buildZipSrc).isFile()) throw new IllegalArgumentError('buildZipFile does not exists', buildZipSrc)
113+
if (!tag) throw new MissingArgumentError('tag is required')
106114

107115
try {
108-
await this.copyFiles(podName, [buildZipSrc], constants.HEDERA_USER_HOME_DIR)
109-
return this.extractPlatform(podName, buildZipSrc)
116+
const releaseDir = Templates.prepareReleasePrefix(tag)
117+
const packageURL = `${constants.HEDERA_BUILDS_URL}/node/software/${releaseDir}/build-${tag}.zip`
118+
const buildZip = path.join(constants.HEDERA_USER_HOME_DIR, `build-${tag}.zip`)
119+
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `curl -s ${packageURL} -o ${buildZip}`)
120+
return this.extractPlatform(podName, buildZip)
110121
} catch (e) {
111122
throw new FullstackTestingError(`failed to copy platform code in to pod '${podName}': ${e.message}`, e)
112123
}

src/core/templates.mjs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
*
1616
*/
1717
import * as x509 from '@peculiar/x509'
18-
import { DataValidationError, MissingArgumentError } from './errors.mjs'
18+
import path from 'path'
19+
import { DataValidationError, IllegalArgumentError, MissingArgumentError } from './errors.mjs'
1920

2021
export class Templates {
2122
static renderNetworkPodName (nodeId) {
@@ -116,4 +117,24 @@ export class Templates {
116117
) {
117118
return new x509.Name(`CN=${nodeId},ST=${state},L=${locality},O=${org},OU=${orgUnit},C=${country}`)
118119
}
120+
121+
static renderStagingDir (configManager, flags) {
122+
if (!configManager) throw new MissingArgumentError('configManager is required')
123+
const cacheDir = configManager.getFlag(flags.cacheDir)
124+
if (!cacheDir) {
125+
throw new IllegalArgumentError('cacheDir cannot be empty')
126+
}
127+
128+
const releaseTag = configManager.getFlag(flags.releaseTag)
129+
if (!releaseTag) {
130+
throw new IllegalArgumentError('releaseTag cannot be empty')
131+
}
132+
133+
const releasePrefix = this.prepareReleasePrefix(releaseTag)
134+
if (!releasePrefix) {
135+
throw new IllegalArgumentError('releasePrefix cannot be empty')
136+
}
137+
138+
return path.resolve(`${cacheDir}/${releasePrefix}/staging/${releaseTag}`)
139+
}
119140
}

test/e2e/core/platform_installer_e2e.test.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ describe('PackageInstallerE2E', () => {
3737
const testCacheDir = getTestCacheDir()
3838
const podName = 'network-node0-0'
3939
const packageVersion = 'v0.42.5'
40-
let packageFile = ''
4140

4241
beforeAll(async () => {
4342
if (!fs.existsSync(testCacheDir)) {
@@ -73,8 +72,7 @@ describe('PackageInstallerE2E', () => {
7372
it('should succeed with valid tag and pod', async () => {
7473
expect.assertions(1)
7574
try {
76-
packageFile = await downloader.fetchPlatform(packageVersion, testCacheDir)
77-
await expect(installer.copyPlatform(podName, packageFile, true)).resolves.toBeTruthy()
75+
await expect(installer.fetchPlatform(podName, packageVersion)).resolves.toBeTruthy()
7876
const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`)
7977
testLogger.showUser(outputs)
8078
} catch (e) {

test/unit/core/platform_installer.test.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ describe('PackageInstaller', () => {
9393
describe('extractPlatform', () => {
9494
it('should fail for missing pod name', async () => {
9595
expect.assertions(1)
96-
await expect(installer.copyPlatform('', os.tmpdir())).rejects.toThrow(MissingArgumentError)
96+
await expect(installer.fetchPlatform('', 'v0.42.5')).rejects.toThrow(MissingArgumentError)
9797
})
98-
it('should fail for missing buildZipFile path', async () => {
98+
it('should fail for missing tag', async () => {
9999
expect.assertions(1)
100-
await expect(installer.copyPlatform('network-node0-0', '')).rejects.toThrow(MissingArgumentError)
100+
await expect(installer.fetchPlatform('network-node0-0', '')).rejects.toThrow(MissingArgumentError)
101101
})
102102
})
103103

0 commit comments

Comments
 (0)