@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
263 lines • 11.6 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import fs from 'node:fs';
import * as constants from './constants.js';
import { PathEx } from '../business/utils/path-ex.js';
import yaml from 'yaml';
export class HelmValuesHelper {
constructor() { }
buildPerNodeExtraEnvironmentValuesStructure(consensusNodes, options = {}) {
const hedera = { nodes: [] };
for (const [nodeIndex, consensusNode] of consensusNodes.entries()) {
const extraEnvironmentVariables = [
...(options.baseExtraEnvironmentVariables?.[consensusNode.name] ?? []),
];
if (options.useJavaMainClass) {
this.setExtraEnvironmentVariable(extraEnvironmentVariables, 'JAVA_MAIN_CLASS', 'com.swirlds.platform.Browser');
}
if (options.wrapsEnabled && options.tss) {
const wrapPath = `${constants.HEDERA_HAPI_PATH}/${options.tss.wraps.artifactsFolderName}`;
this.setExtraEnvironmentVariable(extraEnvironmentVariables, 'TSS_LIB_WRAPS_ARTIFACTS_PATH', wrapPath);
}
if (options.debugNodeAlias === consensusNode.name) {
const debugJavaOptions = `-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:${constants.JVM_DEBUG_PORT}`;
const javaOptionsIndex = extraEnvironmentVariables.findIndex((environmentVariable) => environmentVariable.name === 'JAVA_OPTS');
if (javaOptionsIndex === -1) {
extraEnvironmentVariables.push({
name: 'JAVA_OPTS',
value: debugJavaOptions,
});
}
else {
extraEnvironmentVariables[javaOptionsIndex].value =
`${debugJavaOptions} ${extraEnvironmentVariables[javaOptionsIndex].value}`.trim();
}
}
if (options.additionalEnvironmentVariables && options.additionalEnvironmentVariables[consensusNode.name]) {
for (const additionalEnvironmentVariable of options.additionalEnvironmentVariables[consensusNode.name]) {
this.setExtraEnvironmentVariable(extraEnvironmentVariables, additionalEnvironmentVariable.name, additionalEnvironmentVariable.value);
}
}
const finalJavaOptionsIndex = extraEnvironmentVariables.findIndex((environmentVariable) => environmentVariable.name === 'JAVA_OPTS');
if (finalJavaOptionsIndex !== -1) {
extraEnvironmentVariables[finalJavaOptionsIndex].value = this.sanitizeJavaOptionsForHeapSettings(extraEnvironmentVariables[finalJavaOptionsIndex].value);
}
while (hedera.nodes.length <= nodeIndex) {
hedera.nodes.push({});
}
const nodeValues = {};
if (extraEnvironmentVariables.length > 0) {
nodeValues.root = { extraEnv: extraEnvironmentVariables };
}
const additionalNodeValues = options.additionalNodeValues?.[consensusNode.name];
if (additionalNodeValues?.name) {
nodeValues.name = additionalNodeValues.name;
}
if (typeof additionalNodeValues?.nodeId === 'number') {
nodeValues.nodeId = additionalNodeValues.nodeId;
}
if (additionalNodeValues?.accountId) {
nodeValues.accountId = additionalNodeValues.accountId;
}
if (additionalNodeValues?.blockNodesJson) {
nodeValues.blockNodesJson = additionalNodeValues.blockNodesJson;
}
hedera.nodes[nodeIndex] = nodeValues;
}
return { hedera };
}
generateExtraEnvironmentValuesFile(consensusNodes, options = {}, cacheDirectory) {
const perNodeExtraEnvironmentValues = this.buildPerNodeExtraEnvironmentValuesStructure(consensusNodes, options);
const filename = `per-node-extra-env-${Date.now()}-${Math.random().toString(36).slice(2)}.yaml`;
const filePath = PathEx.join(cacheDirectory, filename);
const yamlContent = yaml.stringify(perNodeExtraEnvironmentValues, { indent: 2 });
fs.writeFileSync(filePath, yamlContent);
return filePath;
}
parseValuesFilePaths(valuesArgument) {
const filePaths = [];
const regex = /--values\s+"([^"]+)"|--values\s+(\S+)/g;
let match;
while ((match = regex.exec(valuesArgument)) !== null) {
filePaths.push(match[1] ?? match[2]);
}
return filePaths;
}
parseValuesFile(filePath) {
let content;
try {
content = fs.readFileSync(filePath, 'utf8');
}
catch {
return undefined;
}
let parsedValues;
try {
parsedValues = yaml.parse(content);
}
catch {
return undefined;
}
if (!parsedValues || typeof parsedValues !== 'object') {
return undefined;
}
return parsedValues;
}
readHederaNodes(valuesFilePath) {
const parsedRecord = this.parseValuesFile(valuesFilePath);
if (!parsedRecord) {
return undefined;
}
const hederaSection = parsedRecord.hedera;
if (!hederaSection || typeof hederaSection !== 'object') {
return undefined;
}
const nodesArray = hederaSection.nodes;
if (!Array.isArray(nodesArray)) {
return undefined;
}
return nodesArray;
}
extractExtraEnvironmentFromValuesFiles(filePaths, consensusNodes) {
const result = {};
for (const filePath of filePaths) {
const parsedRecord = this.parseValuesFile(filePath);
if (!parsedRecord) {
continue;
}
const defaultsSection = parsedRecord.defaults;
if (defaultsSection && typeof defaultsSection === 'object') {
const defaultsRootSection = defaultsSection.root;
const defaultsEnvironmentVariables = this.extractExtraEnvironmentArray(defaultsRootSection);
if (defaultsEnvironmentVariables.length > 0) {
for (const consensusNode of consensusNodes) {
this.mergeIntoResult(result, consensusNode.name, defaultsEnvironmentVariables);
}
}
}
const hederaSection = parsedRecord.hedera;
if (!hederaSection || typeof hederaSection !== 'object') {
continue;
}
const nodesArray = hederaSection.nodes;
if (!Array.isArray(nodesArray)) {
continue;
}
for (const [helmNodeIndex, consensusNode] of consensusNodes.entries()) {
const nodeEntry = nodesArray[helmNodeIndex];
if (!nodeEntry || typeof nodeEntry !== 'object') {
continue;
}
const nodeRootSection = nodeEntry.root;
const nodeEnvironmentVariables = this.extractExtraEnvironmentArray(nodeRootSection);
if (nodeEnvironmentVariables.length > 0) {
this.mergeIntoResult(result, consensusNode.name, nodeEnvironmentVariables);
}
}
}
return result;
}
extractPerNodeBlockNodesJsonFromValuesFile(valuesFilePath, consensusNodes) {
const result = {};
const nodesArray = this.readHederaNodes(valuesFilePath);
if (!nodesArray) {
return result;
}
for (const [helmNodeIndex, consensusNode] of consensusNodes.entries()) {
const nodeEntry = nodesArray[helmNodeIndex];
if (!nodeEntry || typeof nodeEntry !== 'object') {
continue;
}
const blockNodesJson = nodeEntry.blockNodesJson;
if (typeof blockNodesJson === 'string') {
result[consensusNode.name] = blockNodesJson;
}
}
return result;
}
extractPerNodeIdentityFromValuesFile(valuesFilePath, consensusNodes) {
const result = {};
const nodesArray = this.readHederaNodes(valuesFilePath);
if (!nodesArray) {
return result;
}
for (const [helmNodeIndex, consensusNode] of consensusNodes.entries()) {
const nodeEntry = nodesArray[helmNodeIndex];
if (!nodeEntry || typeof nodeEntry !== 'object') {
continue;
}
const entry = nodeEntry;
const identity = {};
if (typeof entry.name === 'string') {
identity.name = entry.name;
}
if (typeof entry.nodeId === 'number') {
identity.nodeId = entry.nodeId;
}
else if (typeof entry.nodeId === 'string') {
const parsed = Number.parseInt(entry.nodeId, 10);
if (!Number.isNaN(parsed)) {
identity.nodeId = parsed;
}
}
if (typeof entry.accountId === 'string') {
identity.accountId = entry.accountId;
}
result[consensusNode.name] = identity;
}
return result;
}
sanitizeJavaOptionsForHeapSettings(javaOptions) {
return javaOptions
.replaceAll(/(^|\s)-Xms\s*\S+/g, '$1')
.replaceAll(/(^|\s)-Xmx\s*\S+/g, '$1')
.replaceAll(/\s+/g, ' ')
.trim();
}
setExtraEnvironmentVariable(extraEnvironmentVariables, name, value) {
const environmentVariableIndex = extraEnvironmentVariables.findIndex((environmentVariable) => environmentVariable.name === name);
if (environmentVariableIndex === -1) {
extraEnvironmentVariables.push({ name, value });
}
else {
extraEnvironmentVariables[environmentVariableIndex].value = value;
}
}
mergeIntoResult(result, nodeAlias, environmentVariables) {
if (!result[nodeAlias]) {
result[nodeAlias] = [];
}
for (const environmentVariable of environmentVariables) {
const existingIndex = result[nodeAlias].findIndex((variable) => variable.name === environmentVariable.name);
const environmentVariableClone = { ...environmentVariable };
if (existingIndex === -1) {
result[nodeAlias].push(environmentVariableClone);
}
else {
result[nodeAlias][existingIndex] = environmentVariableClone;
}
}
}
extractExtraEnvironmentArray(rootSection) {
if (!rootSection || typeof rootSection !== 'object') {
return [];
}
const extraEnvironmentArray = rootSection.extraEnv;
if (!Array.isArray(extraEnvironmentArray)) {
return [];
}
const environmentVariables = [];
for (const entry of extraEnvironmentArray) {
if (!entry || typeof entry !== 'object') {
continue;
}
const entryRecord = entry;
if (typeof entryRecord.name !== 'string' || typeof entryRecord.value !== 'string') {
continue;
}
environmentVariables.push({ name: entryRecord.name, value: entryRecord.value });
}
return environmentVariables;
}
}
export const helmValuesHelper = new HelmValuesHelper();
//# sourceMappingURL=helm-values-helper.js.map