@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
145 lines • 6.97 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { PodRef } from './kube/resources/pod/pod_ref.js';
import { PodName } from './kube/resources/pod/pod_name.js';
import path from 'path';
import { HEDERA_HAPI_PATH, ROOT_CONTAINER, SOLO_LOGS_DIR } from './constants.js';
import fs from 'fs';
import { ContainerRef } from './kube/resources/container/container_ref.js';
import * as constants from './constants.js';
import { sleep } from './helpers.js';
import { Duration } from './time/duration.js';
import { inject, injectable } from 'tsyringe-neo';
import { patchInject } from './dependency_injection/container_helper.js';
import { InjectTokens } from './dependency_injection/inject_tokens.js';
/**
* Class to manage network nodes
*/
let NetworkNodes = class NetworkNodes {
logger;
k8Factory;
constructor(logger, k8Factory) {
this.logger = logger;
this.k8Factory = k8Factory;
this.logger = patchInject(logger, InjectTokens.SoloLogger, this.constructor.name);
this.k8Factory = patchInject(k8Factory, InjectTokens.K8Factory, this.constructor.name);
}
/**
* Download logs files from all network pods and save to local solo log directory
* @param namespace - the namespace of the network
* @returns a promise that resolves when the logs are downloaded
*/
async getLogs(namespace) {
const pods = await this.k8Factory.default().pods().list(namespace, ['solo.hedera.com/type=network-node']);
const timeString = new Date().toISOString().replace(/:/g, '-').replace(/\./g, '-');
const promises = [];
for (const pod of pods) {
promises.push(this.getLog(pod, namespace, timeString));
}
return await Promise.all(promises);
}
async getLog(pod, namespace, timeString) {
const podRef = PodRef.of(namespace, PodName.of(pod.metadata.name));
this.logger.debug(`getNodeLogs(${pod.metadata.name}): begin...`);
const targetDir = path.join(SOLO_LOGS_DIR, namespace.name, timeString);
try {
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
const containerRef = ContainerRef.of(podRef, ROOT_CONTAINER);
const scriptName = 'support-zip.sh';
const sourcePath = path.join(constants.RESOURCES_DIR, scriptName); // script source path
await this.k8Factory.default().containers().readByRef(containerRef).copyTo(sourcePath, `${HEDERA_HAPI_PATH}`);
await sleep(Duration.ofSeconds(3)); // wait for the script to sync to the file system
await this.k8Factory
.default()
.containers()
.readByRef(containerRef)
.execContainer([
'bash',
'-c',
`sync ${HEDERA_HAPI_PATH} && sudo chown hedera:hedera ${HEDERA_HAPI_PATH}/${scriptName}`,
]);
await this.k8Factory
.default()
.containers()
.readByRef(containerRef)
.execContainer(['bash', '-c', `sudo chmod 0755 ${HEDERA_HAPI_PATH}/${scriptName}`]);
await this.k8Factory
.default()
.containers()
.readByRef(containerRef)
.execContainer(`${HEDERA_HAPI_PATH}/${scriptName}`);
await this.k8Factory
.default()
.containers()
.readByRef(containerRef)
.copyFrom(`${HEDERA_HAPI_PATH}/data/${podRef.name}.zip`, targetDir);
}
catch (e) {
// not throw error here, so we can continue to finish downloading logs from other pods
// and also delete namespace in the end
this.logger.error(`${constants.NODE_LOG_FAILURE_MSG} ${podRef}`, e);
}
this.logger.debug(`getNodeLogs(${pod.metadata.name}): ...end`);
}
/**
* Download state files from a pod
* @param namespace - the namespace of the network
* @param nodeAlias - the pod name
* @returns a promise that resolves when the state files are downloaded
*/
async getStatesFromPod(namespace, nodeAlias) {
const pods = await this.k8Factory
.default()
.pods()
.list(namespace, [`solo.hedera.com/node-name=${nodeAlias}`, 'solo.hedera.com/type=network-node']);
// get length of pods
const promises = [];
for (const pod of pods) {
promises.push(this.getState(pod, namespace));
}
return await Promise.all(promises);
}
async getState(pod, namespace) {
const podRef = PodRef.of(namespace, PodName.of(pod.metadata.name));
this.logger.debug(`getNodeState(${pod.metadata.name}): begin...`);
const targetDir = path.join(SOLO_LOGS_DIR, namespace.name);
try {
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
const zipCommand = `tar -czf ${HEDERA_HAPI_PATH}/${podRef.name}-state.zip -C ${HEDERA_HAPI_PATH}/data/saved .`;
const containerRef = ContainerRef.of(podRef, ROOT_CONTAINER);
await this.k8Factory.default().containers().readByRef(containerRef).execContainer(zipCommand);
await this.k8Factory
.default()
.containers()
.readByRef(containerRef)
.copyFrom(`${HEDERA_HAPI_PATH}/${podRef.name}-state.zip`, targetDir);
}
catch (e) {
this.logger.error(`failed to download state from pod ${podRef.name}`, e);
this.logger.showUser(`Failed to download state from pod ${podRef.name}` + e);
}
this.logger.debug(`getNodeState(${pod.metadata.name}): ...end`);
}
};
NetworkNodes = __decorate([
injectable(),
__param(0, inject(InjectTokens.SoloLogger)),
__param(1, inject(InjectTokens.K8Factory)),
__metadata("design:paramtypes", [Function, Object])
], NetworkNodes);
export { NetworkNodes };
//# sourceMappingURL=network_nodes.js.map