Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): allow user to set jvm options for Hedera nodes #84

Merged
merged 5 commits into from
Feb 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/commands/flags.mjs
Original file line number Diff line number Diff line change
@@ -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: {
@@ -454,7 +463,8 @@ export const allFlags = [
updateAccountKeys,
privateKey,
accountId,
amount
amount,
applicationEnv
]

export const allFlagsMap = new Map(allFlags.map(f => [f.name, f]))
41 changes: 23 additions & 18 deletions src/commands/node.mjs
Original file line number Diff line number Diff line change
@@ -194,7 +194,7 @@
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) {
@@ -227,15 +227,6 @@
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, _) => {
@@ -349,7 +340,7 @@
}
},
{
title: 'Upload platform software into network nodes',
title: 'Fetch platform software into network nodes',
task:
async (ctx, task) => {
const config = ctx.config
@@ -360,7 +351,7 @@
subTasks.push({
title: `Node: ${chalk.yellow(nodeId)}`,
task: () =>
self.plaformInstaller.copyPlatform(podName, config.buildZipFile)
self.plaformInstaller.fetchPlatform(podName, config.releaseTag)
})
}

@@ -428,17 +419,21 @@

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)) {
@@ -460,6 +455,15 @@
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}`)

Check warning on line 464 in src/commands/node.mjs

Codecov / codecov/patch

src/commands/node.mjs#L461-L464

Added lines #L461 - L464 were not covered by tests
}

await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['systemctl', 'restart', 'network-node'])
}
})
@@ -818,7 +822,8 @@
builder: y => flags.setCommandFlags(y,
flags.namespace,
flags.nodeIDs,
flags.updateAccountKeys
flags.updateAccountKeys,
flags.applicationEnv
),
handler: argv => {
nodeCmd.logger.debug("==== Running 'node start' ===")
21 changes: 16 additions & 5 deletions src/core/platform_installer.mjs
Original file line number Diff line number Diff line change
@@ -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)
}
23 changes: 22 additions & 1 deletion src/core/templates.mjs
Original file line number Diff line number Diff line change
@@ -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) {
@@ -116,4 +117,24 @@
) {
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')

Check warning on line 125 in src/core/templates.mjs

Codecov / codecov/patch

src/core/templates.mjs#L125

Added line #L125 was not covered by tests
}

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

Check warning on line 130 in src/core/templates.mjs

Codecov / codecov/patch

src/core/templates.mjs#L130

Added line #L130 was not covered by tests
}

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

Check warning on line 135 in src/core/templates.mjs

Codecov / codecov/patch

src/core/templates.mjs#L135

Added line #L135 was not covered by tests
}

return path.resolve(`${cacheDir}/${releasePrefix}/staging/${releaseTag}`)

Check warning on line 138 in src/core/templates.mjs

Codacy Production / Codacy Static Code Analysis

src/core/templates.mjs#L138

Detected possible user input going into a `path.join` or `path.resolve` function.
}
}
4 changes: 1 addition & 3 deletions test/e2e/core/platform_installer_e2e.test.mjs
Original file line number Diff line number Diff line change
@@ -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)) {
@@ -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) {
6 changes: 3 additions & 3 deletions test/unit/core/platform_installer.test.mjs
Original file line number Diff line number Diff line change
@@ -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)
})
})