From a1dd991769654c2fb3eb5269f7b3a89b40ac76ce Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Tue, 9 Apr 2024 12:36:36 -0500 Subject: [PATCH 01/10] feat: adding some type check --- src/commands/account.mjs | 14 +++++++++----- src/commands/base.mjs | 4 ++-- src/commands/cluster.mjs | 19 +++++++++++-------- src/commands/init.mjs | 5 ++++- src/commands/mirror_node.mjs | 7 +++++-- src/commands/network.mjs | 9 ++++++--- src/commands/node.mjs | 16 ++++++++++++---- src/core/account_manager.mjs | 2 +- src/core/chart_manager.mjs | 2 +- 9 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/commands/account.mjs b/src/commands/account.mjs index 0c17599a2..698161e48 100644 --- a/src/commands/account.mjs +++ b/src/commands/account.mjs @@ -16,12 +16,13 @@ */ import chalk from 'chalk' import { BaseCommand } from './base.mjs' -import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' +import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from '../core/errors.mjs' import { flags } from './index.mjs' import { Listr } from 'listr2' import * as prompts from './prompts.mjs' import { constants } from '../core/index.mjs' -import { HbarUnit, PrivateKey } from '@hashgraph/sdk' +import { AccountInfo, HbarUnit, PrivateKey } from '@hashgraph/sdk' +import AccountId from '@hashgraph/sdk/lib/account/AccountId.js' export class AccountCommand extends BaseCommand { constructor (opts, systemAccounts = constants.SYSTEM_ACCOUNTS) { @@ -38,7 +39,9 @@ export class AccountCommand extends BaseCommand { await this.accountManager.close() } - async buildAccountInfo (accountInfo, namespace, shouldRetrievePrivateKey) { + async buildAccountInfo (accountInfo, namespace: string, shouldRetrievePrivateKey: boolean) { + if (!accountInfo || !(accountInfo instanceof AccountInfo)) throw new MissingArgumentError('An instance of AccountInfo is required') + const newAccountInfo = { accountId: accountInfo.accountId.toString(), publicKey: accountInfo.key.toString(), @@ -94,7 +97,7 @@ export class AccountCommand extends BaseCommand { return true } - async transferAmountFromOperator (toAccountId, amount) { + async transferAmountFromOperator (toAccountId: AccountId, amount: number) { return await this.accountManager.transferAmount(constants.TREASURY_ACCOUNT_ID, toAccountId, amount) } @@ -398,7 +401,8 @@ export class AccountCommand extends BaseCommand { * Return Yargs command definition for 'node' command * @param accountCmd an instance of NodeCommand */ - static getCommandDefinition (accountCmd) { + static getCommandDefinition (accountCmd: AccountCommand) { + if (!accountCmd | !(accountCmd instanceof AccountCommand)) throw new IllegalArgumentError('An instance of AccountCommand is required', accountCmd) return { command: 'account', desc: 'Manage Hedera accounts in fullstack testing network', diff --git a/src/commands/base.mjs b/src/commands/base.mjs index 9e997f625..f44327aad 100644 --- a/src/commands/base.mjs +++ b/src/commands/base.mjs @@ -20,7 +20,7 @@ import { MissingArgumentError } from '../core/errors.mjs' import { ShellRunner } from '../core/shell_runner.mjs' export class BaseCommand extends ShellRunner { - async prepareChartPath (chartDir, chartRepo, chartReleaseName) { + async prepareChartPath (chartDir: string, chartRepo: string, chartReleaseName: string) { if (!chartRepo) throw new MissingArgumentError('chart repo name is required') if (!chartReleaseName) throw new MissingArgumentError('chart release name is required') @@ -32,7 +32,7 @@ export class BaseCommand extends ShellRunner { return `${chartRepo}/${chartReleaseName}` } - prepareValuesFiles (valuesFile) { + prepareValuesFiles (valuesFile: string) { let valuesArg = '' if (valuesFile) { const valuesFiles = valuesFile.split(',') diff --git a/src/commands/cluster.mjs b/src/commands/cluster.mjs index cf2336fa2..d63f7ad25 100644 --- a/src/commands/cluster.mjs +++ b/src/commands/cluster.mjs @@ -53,7 +53,7 @@ export class ClusterCommand extends BaseCommand { * Show list of installed chart * @param clusterSetupNamespace */ - async showInstalledChartList (clusterSetupNamespace) { + async showInstalledChartList (clusterSetupNamespace: string) { this.logger.showList('Installed Charts', await this.chartManager.getInstalledCharts(clusterSetupNamespace)) } @@ -219,7 +219,10 @@ export class ClusterCommand extends BaseCommand { * Return Yargs command definition for 'cluster' command * @param clusterCmd an instance of ClusterCommand */ - static getCommandDefinition (clusterCmd) { + static getCommandDefinition (clusterCmd: ClusterCommand) { + if (!clusterCmd || !(clusterCmd instanceof ClusterCommand)) { + throw new FullstackTestingError('Invalid ClusterCommand instance') + } return { command: 'cluster', desc: 'Manage fullstack testing cluster', @@ -318,11 +321,11 @@ export class ClusterCommand extends BaseCommand { * @param certManagerCrdsEnabled a bool to denote whether to install cert manager CRDs * @returns {string} */ - prepareValuesArg (chartDir = flags.chartDirectory.definition.default, - prometheusStackEnabled = flags.deployPrometheusStack.definition.default, - minioEnabled = flags.deployMinio.definition.default, - certManagerEnabled = flags.deployCertManager.definition.default, - certManagerCrdsEnabled = flags.deployCertManagerCrds.definition.default + prepareValuesArg (chartDir: string = flags.chartDirectory.definition.default, + prometheusStackEnabled: boolean = flags.deployPrometheusStack.definition.default, + minioEnabled: boolean = flags.deployMinio.definition.default, + certManagerEnabled: boolean = flags.deployCertManager.definition.default, + certManagerCrdsEnabled: boolean = flags.deployCertManagerCrds.definition.default ) { let valuesArg = '' if (chartDir) { @@ -347,7 +350,7 @@ export class ClusterCommand extends BaseCommand { * @param chartDir local charts directory (default is empty) * @returns {Promise} */ - async prepareChartPath (chartDir = flags.chartDirectory.definition.default) { + async prepareChartPath (chartDir: string = flags.chartDirectory.definition.default) { let chartPath = 'full-stack-testing/fullstack-cluster-setup' if (chartDir) { chartPath = `${chartDir}/fullstack-cluster-setup` diff --git a/src/commands/init.mjs b/src/commands/init.mjs index 40a525acc..c3eab2f9e 100644 --- a/src/commands/init.mjs +++ b/src/commands/init.mjs @@ -143,7 +143,10 @@ export class InitCommand extends BaseCommand { * Return Yargs command definition for 'init' command * @param initCmd an instance of InitCommand */ - static getCommandDefinition (initCmd) { + static getCommandDefinition (initCmd: InitCommand) { + if (!initCmd || !(initCmd instanceof InitCommand)) { + throw new FullstackTestingError('Invalid InitCommand instance') + } return { command: 'init', desc: 'Initialize local environment and default flags', diff --git a/src/commands/mirror_node.mjs b/src/commands/mirror_node.mjs index cc6b90254..3653c484f 100644 --- a/src/commands/mirror_node.mjs +++ b/src/commands/mirror_node.mjs @@ -32,7 +32,7 @@ export class MirrorNodeCommand extends BaseCommand { this.profileManager = opts.profileManager } - async prepareValuesArg (valuesFile, deployHederaExplorer) { + async prepareValuesArg (valuesFile: string, deployHederaExplorer:boolean) { let valuesArg = '' if (valuesFile) { valuesArg += this.prepareValuesFiles(valuesFile) @@ -279,7 +279,10 @@ export class MirrorNodeCommand extends BaseCommand { * Return Yargs command definition for 'mirror-mirror-node' command * @param mirrorNodeCmd an instance of NodeCommand */ - static getCommandDefinition (mirrorNodeCmd) { + static getCommandDefinition (mirrorNodeCmd: MirrorNodeCommand) { + if (!mirrorNodeCmd || !(mirrorNodeCmd instanceof MirrorNodeCommand)) { + throw new IllegalArgumentError('Invalid MirrorNodeCommand instance', mirrorNodeCmd) + } return { command: 'mirror-node', desc: 'Manage Hedera Mirror Node in fullstack testing network', diff --git a/src/commands/network.mjs b/src/commands/network.mjs index c4d3f1c46..7cb892a0d 100644 --- a/src/commands/network.mjs +++ b/src/commands/network.mjs @@ -33,8 +33,8 @@ export class NetworkCommand extends BaseCommand { this.profileManager = opts.profileManager } - getTlsValueArguments (tlsClusterIssuerType, enableHederaExplorerTls, namespace, - hederaExplorerTlsLoadBalancerIp, hederaExplorerTlsHostName) { + getTlsValueArguments (tlsClusterIssuerType: string, enableHederaExplorerTls: boolean, namespace: string, + hederaExplorerTlsLoadBalancerIp: string, hederaExplorerTlsHostName: string) { let valuesArg = '' if (enableHederaExplorerTls) { @@ -392,7 +392,10 @@ export class NetworkCommand extends BaseCommand { return true } - static getCommandDefinition (networkCmd) { + static getCommandDefinition (networkCmd: NetworkCommand) { + if (!networkCmd || !(networkCmd instanceof NetworkCommand)) { + throw new MissingArgumentError('An instance of NetworkCommand is required', networkCmd) + } return { command: 'network', desc: 'Manage fullstack testing network deployment', diff --git a/src/commands/node.mjs b/src/commands/node.mjs index 6e9202760..613a450ba 100644 --- a/src/commands/node.mjs +++ b/src/commands/node.mjs @@ -61,7 +61,7 @@ export class NodeCommand extends BaseCommand { this._portForwards = [] } - async checkNetworkNodePod (namespace, nodeId) { + async checkNetworkNodePod (namespace: string, nodeId: string) { nodeId = nodeId.trim() const podName = Templates.renderNetworkPodName(nodeId) @@ -77,7 +77,7 @@ export class NodeCommand extends BaseCommand { } } - async checkNetworkNodeStarted (nodeId, maxAttempt = 100, status = 'ACTIVE') { + async checkNetworkNodeStarted (nodeId: string, maxAttempt: number = 100, status: string = 'ACTIVE') { nodeId = nodeId.trim() const podName = Templates.renderNetworkPodName(nodeId) const logfilePath = `${constants.HEDERA_HAPI_PATH}/logs/hgcaa.log` @@ -176,7 +176,11 @@ export class NodeCommand extends BaseCommand { * @return a list of subtasks * @private */ - _nodeGossipKeysTaskList (keyFormat, nodeIds, keysDir, curDate = new Date()) { + _nodeGossipKeysTaskList (keyFormat: string, nodeIds: Array, keysDir: string, curDate = new Date()) { + // check if nodeIds is an array of strings + if (!Array.isArray(nodeIds) || !nodeIds.every((nodeId) => typeof nodeId === 'string')) { + throw new FullstackTestingError('nodeIds must be an array of strings') + } const self = this const subTasks = [] @@ -274,7 +278,11 @@ export class NodeCommand extends BaseCommand { * @return return a list of subtasks * @private */ - _nodeTlsKeyTaskList (nodeIds, keysDir, curDate = new Date()) { + _nodeTlsKeyTaskList (nodeIds: Array, keysDir: string, curDate = new Date()) { + // check if nodeIds is an array of strings + if (!Array.isArray(nodeIds) || !nodeIds.every((nodeId) => typeof nodeId === 'string')) { + throw new FullstackTestingError('nodeIds must be an array of strings') + } const self = this const nodeKeyFiles = new Map() const subTasks = [] diff --git a/src/core/account_manager.mjs b/src/core/account_manager.mjs index 983f57850..f44232279 100644 --- a/src/core/account_manager.mjs +++ b/src/core/account_manager.mjs @@ -520,7 +520,7 @@ export class AccountManager { * @param hbarAmount the amount of HBAR * @returns {Promise} if the transaction was successfully posted */ - async transferAmount (fromAccountId, toAccountId, hbarAmount) { + async transferAmount (fromAccountId: AccountId, toAccountId: AccountId, hbarAmount:number) { try { const transaction = new TransferTransaction() .addHbarTransfer(fromAccountId, new Hbar(-1 * hbarAmount)) diff --git a/src/core/chart_manager.mjs b/src/core/chart_manager.mjs index 52c91c390..924ccb432 100644 --- a/src/core/chart_manager.mjs +++ b/src/core/chart_manager.mjs @@ -60,7 +60,7 @@ export class ChartManager { * List available clusters * @returns {Promise} */ - async getInstalledCharts (namespaceName) { + async getInstalledCharts (namespaceName: string) { try { return await this.helm.list(`-n ${namespaceName}`, '--no-headers | awk \'{print $1 " [" $9"]"}\'') } catch (e) { From eb7324197cc2760f5cb9fd33327c93773bca3062 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:42:03 +0000 Subject: [PATCH 02/10] auto update README.md --- README.md | 418 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 247 insertions(+), 171 deletions(-) diff --git a/README.md b/README.md index 6805dd7eb..eafdc758c 100644 --- a/README.md +++ b/README.md @@ -72,11 +72,15 @@ export SOLO_CLUSTER_SETUP_NAMESPACE=solo-cluster Then run the following command to set the kubectl context to the new cluster: -``` +```bash kind create cluster -n "${SOLO_CLUSTER_NAME}" +``` +Example output + +``` Creating cluster "solo" ... - ✓ Ensuring node image (kindest/node:v1.27.3) đŸ–ŧ - ✓ Preparing nodes đŸ“Ļ + ✓ Ensuring node image (kindest/node:v1.29.1) đŸ–ŧ + ✓ Preparing nodes đŸ“Ļ ✓ Writing configuration 📜 ✓ Starting control-plane 🕹ī¸ ✓ Installing CNI 🔌 @@ -86,7 +90,7 @@ You can now use your cluster with: kubectl cluster-info --context kind-solo -Have a nice day! 👋 +Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂 ``` You may now view pods in your cluster using `k9s -A` as below: @@ -122,26 +126,28 @@ You may now view pods in your cluster using `k9s -A` as below: ``` $ solo init -t v0.42.5 -i node0,node1,node2 -n "${SOLO_NAMESPACE}" -s "${SOLO_CLUSTER_SETUP_NAMESPACE}" --key-format pfx +``` + +Example output + +``` ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Setup home directory and cache -✔ Check dependencies [17s] - ✔ Check dependency: helm [OS: darwin, Release: 22.6.0, Arch: arm64] [7s] - ✔ Check dependency: keytool [OS: darwin, Release: 22.6.0, Arch: arm64] [17s] -✔ Setup chart manager [1s] -✔ Copy configuration file templates - +✔ Setup home directory and cache +✔ Check dependency: helm [OS: linux, Release: 5.15.0-1050-gke, Arch: x64] +✔ Check dependencies +✔ Setup chart manager *************************************************************************************** -Note: solo stores various artifacts (config, logs, keys etc.) in its home directory: /Users/leninmehedy/.solo +Note: solo stores various artifacts (config, logs, keys etc.) in its home directory: /home/runner/.solo If a full reset is needed, delete the directory or relevant sub-directories before running 'solo init'. *************************************************************************************** - +✔ Copy configuration file templates ``` * Generate `pfx` formatted node keys @@ -150,70 +156,89 @@ We need to generate `pfx` keys as `pem` key files are only supported by Hedera p ``` $ solo node keys --gossip-keys --tls-keys --key-format pfx +``` + +Example output + +``` ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize -✔ Generate gossip keys -✔ Generate gRPC TLS keys -✔ Finalize +✔ Initialize +✔ Check keytool exists (Version: 21.0.1+12) +✔ Backup old files +✔ Generate private-node0.pfx for node: node0 +✔ Generate private-node1.pfx for node: node1 +✔ Generate private-node2.pfx for node: node2 +✔ Generate public.pfx file +✔ Clean up temp files +✔ Generate gossip keys +✔ Backup old files +✔ TLS key for node: node2 +✔ TLS key for node: node0 +✔ TLS key for node: node1 +✔ Generate gRPC TLS keys +✔ Finalize +``` +Key files are generated in `~/.solo/keys` directory. +``` $ ls ~/.solo/cache/keys hedera-node0.crt hedera-node1.crt hedera-node2.crt private-node0.pfx private-node2.pfx hedera-node0.key hedera-node1.key hedera-node2.key private-node1.pfx public.pfx ``` - * Setup cluster with shared components * In a separate terminal, you may run `k9s` to view the pod status. ``` $ solo cluster setup +``` + +Example output + +``` ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize -✔ Prepare chart values -✔ Install 'fullstack-cluster-setup' chart [1s] - +✔ Initialize +✔ Prepare chart values +✔ Install 'fullstack-cluster-setup' chart ``` + * Deploy helm chart with Hedera network components * It may take a while (5~15 minutes depending on your internet speed) to download various docker images and get the pods started. * If it fails, ensure you have enough resources allocated for Docker engine and retry the command. ``` $ solo network deploy +``` + +Example output + +``` ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize [5s] -✔ Install chart 'fullstack-deployment' [19s] -✔ Check node pods are ready [2s] - ✔ Check Node: node0 [0.8s] - ✔ Check Node: node1 [1s] - ✔ Check Node: node2 [0.9s] -✔ Check proxy pods are ready [0.7s] - ✔ Check HAProxy for: node0 [0.7s] - ✔ Check HAProxy for: node1 [0.7s] - ✔ Check HAProxy for: node2 [0.7s] - ✔ Check Envoy Proxy for: node0 [0.7s] - ✔ Check Envoy Proxy for: node1 [0.7s] - ✔ Check Envoy Proxy for: node2 [0.7s] -✔ Check auxiliary pods are ready [5s] - ✔ Check MinIO [5s] +✔ Initialize +✔ Install chart 'fullstack-deployment' +✔ Node: node0 (Pod: network-node0-0) +✔ Node: node1 (Pod: network-node1-0) +✔ Node: node2 (Pod: network-node2-0) +✔ Waiting for network pods to be ready ``` * Setup node with Hedera platform software. @@ -221,118 +246,141 @@ Kubernetes Namespace : solo ``` $ solo node setup +``` + +Example output + +``` ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize -✔ Identify network pods - ✔ Check network pod: node0 - ✔ Check network pod: node1 - ✔ Check network pod: node2 -↓ Generate Gossip keys -↓ Generate gRPC TLS keys -✔ Prepare staging directory - ✔ Copy configuration files - ✔ Copy Gossip keys to staging - ✔ Copy gRPC TLS keys to staging - ✔ Prepare config.txt for the network -✔ Fetch platform software into network nodes [1m7s] - ✔ Update node: node0 [48s] - ✔ Update node: node1 [44s] - ✔ Update node: node2 [1m7s] -✔ Setup network nodes [1s] - ✔ Node: node0 [1s] - ✔ Copy Gossip keys [0.2s] - ✔ Copy TLS keys [0.2s] - ✔ Copy configuration files [0.7s] - ✔ Set file permissions [0.1s] - ✔ Node: node1 [1s] - ✔ Copy Gossip keys [0.2s] - ✔ Copy TLS keys [0.2s] - ✔ Copy configuration files [0.7s] - ✔ Set file permissions - ✔ Node: node2 [1s] - ✔ Copy Gossip keys [0.2s] - ✔ Copy TLS keys [0.2s] - ✔ Copy configuration files [0.7s] - ✔ Set file permissions [0.1s] -✔ Finalize - +✔ Initialize +✔ Check network pod: node0 +✔ Check network pod: node1 +✔ Check network pod: node2 +✔ Identify network pods +✔ Copy configuration files +✔ Copy Gossip keys to staging +✔ Copy gRPC TLS keys to staging +✔ Prepare config.txt for the network +✔ Prepare staging directory +✔ Node: node1 +✔ Node: node0 +✔ Node: node2 +✔ Fetch platform software into network nodes +✔ Copy Gossip keys +✔ Copy Gossip keys +✔ Copy Gossip keys +✔ Copy TLS keys +✔ Copy TLS keys +✔ Copy TLS keys +✔ Copy configuration files +✔ Copy configuration files +✔ Copy configuration files +✔ Set file permissions +✔ Node: node0 +✔ Set file permissions +✔ Node: node1 +✔ Set file permissions +✔ Node: node2 +✔ Setup network nodes +✔ Finalize ``` * Start the nodes. ``` $ solo node start +``` + +Example output + +``` ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize [0.1s] -✔ Identify network pods - ✔ Check network pod: node0 - ✔ Check network pod: node1 - ✔ Check network pod: node2 -✔ Starting nodes [0.1s] - ✔ Start node: node0 [0.1s] - ✔ Start node: node1 [0.1s] - ✔ Start node: node2 [0.1s] -✔ Check nodes are ACTIVE [24s] - ✔ Check node: node0 [24s] - ✔ Check node: node1 [0.1s] - ✔ Check node: node2 [0.1s] -✔ Check node proxies are ACTIVE [0.1s] - ✔ Check proxy for node: node0 - ✔ Check proxy for node: node1 - ✔ Check proxy for node: node2 +✔ Initialize +✔ Check network pod: node0 +✔ Check network pod: node2 +✔ Check network pod: node1 +✔ Identify network pods +✔ Start node: node1 +✔ Start node: node2 +✔ Start node: node0 +✔ Starting nodes +✔ Check node: node0 +✔ Check node: node1 +✔ Check node: node2 +✔ Check nodes are ACTIVE +✔ Check proxy for node: node0 +✔ Check proxy for node: node1 +✔ Check proxy for node: node2 +✔ Check node proxies are ACTIVE ``` - * Deploy mirror node ``` $ solo mirror-node deploy +``` + +Example output + +``` + ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : kind-solo-e2e -Kubernetes Cluster : kind-solo-e2e -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize [7s] -✔ Enable mirror-node [1m10s] - ✔ Prepare address book [1s] - ✔ Deploy mirror-node [1m9s] -✔ Check pods are ready [59s] - ✔ Check Postgres DB [12s] - ✔ Check REST API [39s] - ✔ Check GRPC [30s] - ✔ Check Monitor [59s] - ✔ Check Importer [48s] - ✔ Check Hedera Explorer [0.7s] +✔ Initialize +✔ Prepare address book +✔ Deploy mirror-node +✔ Enable mirror-node +✔ Check Postgres DB +✔ Check Importer +✔ Check REST API +✔ Check Web3 +✔ Check GRPC +✔ Check Hedera Explorer +✔ Check Mirror node components are ACTIVE ``` * Deploy a JSON RPC relay ``` $ solo relay deploy +``` + +Example output + +``` + ******************************* Solo ********************************************* -Version : 0.22.1 -Kubernetes Context : microk8s -Kubernetes Cluster : microk8s-cluster -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -(node:7924) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead. -(Use `node --trace-deprecation ...` to show where the warning was created) -✔ Initialize [1s] -✔ Prepare chart values -✔ Deploy JSON RPC Relay [9s] -✔ Check relay is ready [21s] +✔ Initialize +✔ Prepare chart values + + *** Deployed Relays *** +------------------------------------------------------------------------------- + - fullstack-deployment [fullstack-deployment-0.24.2] + - relay-node0-node1 [hedera-json-rpc-relay-0.26.0-SNAPSHOT] + - relay-node0-node1-node2 [hedera-json-rpc-relay-0.26.0-SNAPSHOT] + + +✔ Deploy JSON RPC Relay ``` You may view the list of pods using `k9s` as below: @@ -388,18 +436,30 @@ Once the nodes are up, you may now expose various services (using `k9s` (shift-f * You can deploy JSON RPC relays for one or more nodes as below: ``` $ solo relay deploy -i node0,node1 - - ******************************* Solo ********************************************* - Version : 0.22.1 - Kubernetes Context : kind-solo-e2e - Kubernetes Cluster : kind-solo-e2e - Kubernetes Namespace : solo - ********************************************************************************** - ✔ Initialize - ✔ Prepare chart values - ✔ Deploy JSON RPC Relay [1s] ``` +Example output + +``` + +******************************* Solo ********************************************* +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo +********************************************************************************** +✔ Initialize +✔ Prepare chart values + + *** Deployed Relays *** +------------------------------------------------------------------------------- + - fullstack-deployment [fullstack-deployment-0.24.2] + - relay-node0-node1 [hedera-json-rpc-relay-0.26.0-SNAPSHOT] + + +✔ Deploy JSON RPC Relay +``` + ### Example - 2: Deploy a standalone test network (version `0.47.0-alpha.0`) * Initialize `solo` with tag `v0.47.0-alpha.0` and list of node names `node0,node1,node2`: @@ -409,51 +469,67 @@ Once the nodes are up, you may now expose various services (using `k9s` (shift-f $ rm -rf ~/.solo $ solo init -t v0.47.0-alpha.0 -i node0,node1,node2 -n "${SOLO_NAMESPACE}" -s "${SOLO_CLUSTER_SETUP_NAMESPACE}" --key-format pem +``` + +* Example output: + +``` ******************************* Solo ********************************************* -Version : 0.22.0 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Setup home directory and cache -✔ Check dependencies [19s] - ✔ Check dependency: helm [OS: darwin, Release: 22.6.0, Arch: arm64] [8s] - ✔ Check dependency: keytool [OS: darwin, Release: 22.6.0, Arch: arm64] [19s] -✔ Setup chart manager [2s] -✔ Copy configuration file templates - +✔ Setup home directory and cache +✔ Check dependency: helm [OS: linux, Release: 5.15.0-1050-gke, Arch: x64] +✔ Check dependencies +✔ Setup chart manager *************************************************************************************** -Note: solo stores various artifacts (config, logs, keys etc.) in its home directory: /Users/leninmehedy/.solo +Note: solo stores various artifacts (config, logs, keys etc.) in its home directory: /home/runner/.solo If a full reset is needed, delete the directory or relevant sub-directories before running 'solo init'. *************************************************************************************** +✔ Copy configuration file templates ``` * Generate `pem` formatted node keys ``` $ solo node keys --gossip-keys --tls-keys --key-format pem +``` + +* Example output: + +``` ******************************* Solo ********************************************* -Version : 0.22.0 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo +Version : 0.23.0 +Kubernetes Context : kind-solo +Kubernetes Cluster : kind-solo +Kubernetes Namespace : solo ********************************************************************************** -✔ Initialize -✔ Generate gossip keys -✔ Generate gRPC TLS keys -✔ Finalize - +✔ Initialize +✔ Backup old files +✔ Gossip pem key for node: node0 +✔ Gossip pem key for node: node1 +✔ Gossip pem key for node: node2 +✔ Generate gossip keys +✔ Backup old files +✔ TLS key for node: node2 +✔ TLS key for node: node1 +✔ TLS key for node: node0 +✔ Generate gRPC TLS keys +✔ Finalize +``` +PEM key files are generated in `~/.solo/keys` directory. +``` $ ls ~/.solo/cache/keys a-private-node0.pem a-public-node1.pem hedera-node1.crt s-private-node0.pem s-public-node1.pem a-private-node1.pem a-public-node2.pem hedera-node1.key s-private-node1.pem s-public-node2.pem a-private-node2.pem hedera-node0.crt hedera-node2.crt s-private-node2.pem a-public-node0.pem hedera-node0.key hedera-node2.key s-public-node0.pem - ``` - * Setup cluster with shared components ``` From fc60b4bc9ab7d7cdfe844651dfe59c89d56064bf Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Tue, 9 Apr 2024 13:58:00 -0500 Subject: [PATCH 03/10] code check Signed-off-by: Jeffrey Tang --- src/commands/account.mjs | 18 ++++++++++++------ src/commands/base.mjs | 4 ++-- src/commands/cluster.mjs | 16 ++++++++-------- src/commands/init.mjs | 2 +- src/commands/mirror_node.mjs | 4 ++-- src/commands/network.mjs | 6 +++--- src/commands/node.mjs | 11 +++++------ src/core/account_manager.mjs | 9 +++++++-- src/core/chart_manager.mjs | 2 +- 9 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/commands/account.mjs b/src/commands/account.mjs index 698161e48..47a597acd 100644 --- a/src/commands/account.mjs +++ b/src/commands/account.mjs @@ -16,7 +16,7 @@ */ import chalk from 'chalk' import { BaseCommand } from './base.mjs' -import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from '../core/errors.mjs' +import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' import { flags } from './index.mjs' import { Listr } from 'listr2' import * as prompts from './prompts.mjs' @@ -39,8 +39,8 @@ export class AccountCommand extends BaseCommand { await this.accountManager.close() } - async buildAccountInfo (accountInfo, namespace: string, shouldRetrievePrivateKey: boolean) { - if (!accountInfo || !(accountInfo instanceof AccountInfo)) throw new MissingArgumentError('An instance of AccountInfo is required') + async buildAccountInfo (accountInfo, namespace, shouldRetrievePrivateKey) { + if (!accountInfo || !(accountInfo instanceof AccountInfo)) throw new IllegalArgumentError('An instance of AccountInfo is required') const newAccountInfo = { accountId: accountInfo.accountId.toString(), @@ -97,7 +97,11 @@ export class AccountCommand extends BaseCommand { return true } - async transferAmountFromOperator (toAccountId: AccountId, amount: number) { + async transferAmountFromOperator (toAccountId, amount) { + if (!(toAccountId instanceof AccountId)) { + throw new IllegalArgumentError('toAccountId must be an instance of AccountId', toAccountId) + } + return await this.accountManager.transferAmount(constants.TREASURY_ACCOUNT_ID, toAccountId, amount) } @@ -401,8 +405,10 @@ export class AccountCommand extends BaseCommand { * Return Yargs command definition for 'node' command * @param accountCmd an instance of NodeCommand */ - static getCommandDefinition (accountCmd: AccountCommand) { - if (!accountCmd | !(accountCmd instanceof AccountCommand)) throw new IllegalArgumentError('An instance of AccountCommand is required', accountCmd) + static getCommandDefinition (accountCmd) { + if (!accountCmd | !(accountCmd instanceof AccountCommand)) { + throw new IllegalArgumentError('An instance of AccountCommand is required', accountCmd) + } return { command: 'account', desc: 'Manage Hedera accounts in fullstack testing network', diff --git a/src/commands/base.mjs b/src/commands/base.mjs index f44327aad..9e997f625 100644 --- a/src/commands/base.mjs +++ b/src/commands/base.mjs @@ -20,7 +20,7 @@ import { MissingArgumentError } from '../core/errors.mjs' import { ShellRunner } from '../core/shell_runner.mjs' export class BaseCommand extends ShellRunner { - async prepareChartPath (chartDir: string, chartRepo: string, chartReleaseName: string) { + async prepareChartPath (chartDir, chartRepo, chartReleaseName) { if (!chartRepo) throw new MissingArgumentError('chart repo name is required') if (!chartReleaseName) throw new MissingArgumentError('chart release name is required') @@ -32,7 +32,7 @@ export class BaseCommand extends ShellRunner { return `${chartRepo}/${chartReleaseName}` } - prepareValuesFiles (valuesFile: string) { + prepareValuesFiles (valuesFile) { let valuesArg = '' if (valuesFile) { const valuesFiles = valuesFile.split(',') diff --git a/src/commands/cluster.mjs b/src/commands/cluster.mjs index d63f7ad25..f8cd2dd66 100644 --- a/src/commands/cluster.mjs +++ b/src/commands/cluster.mjs @@ -53,7 +53,7 @@ export class ClusterCommand extends BaseCommand { * Show list of installed chart * @param clusterSetupNamespace */ - async showInstalledChartList (clusterSetupNamespace: string) { + async showInstalledChartList (clusterSetupNamespace) { this.logger.showList('Installed Charts', await this.chartManager.getInstalledCharts(clusterSetupNamespace)) } @@ -219,7 +219,7 @@ export class ClusterCommand extends BaseCommand { * Return Yargs command definition for 'cluster' command * @param clusterCmd an instance of ClusterCommand */ - static getCommandDefinition (clusterCmd: ClusterCommand) { + static getCommandDefinition (clusterCmd) { if (!clusterCmd || !(clusterCmd instanceof ClusterCommand)) { throw new FullstackTestingError('Invalid ClusterCommand instance') } @@ -321,11 +321,11 @@ export class ClusterCommand extends BaseCommand { * @param certManagerCrdsEnabled a bool to denote whether to install cert manager CRDs * @returns {string} */ - prepareValuesArg (chartDir: string = flags.chartDirectory.definition.default, - prometheusStackEnabled: boolean = flags.deployPrometheusStack.definition.default, - minioEnabled: boolean = flags.deployMinio.definition.default, - certManagerEnabled: boolean = flags.deployCertManager.definition.default, - certManagerCrdsEnabled: boolean = flags.deployCertManagerCrds.definition.default + prepareValuesArg (chartDir = flags.chartDirectory.definition.default, + prometheusStackEnabled = flags.deployPrometheusStack.definition.default, + minioEnabled = flags.deployMinio.definition.default, + certManagerEnabled = flags.deployCertManager.definition.default, + certManagerCrdsEnabled = flags.deployCertManagerCrds.definition.default ) { let valuesArg = '' if (chartDir) { @@ -350,7 +350,7 @@ export class ClusterCommand extends BaseCommand { * @param chartDir local charts directory (default is empty) * @returns {Promise} */ - async prepareChartPath (chartDir: string = flags.chartDirectory.definition.default) { + async prepareChartPath (chartDir = flags.chartDirectory.definition.default) { let chartPath = 'full-stack-testing/fullstack-cluster-setup' if (chartDir) { chartPath = `${chartDir}/fullstack-cluster-setup` diff --git a/src/commands/init.mjs b/src/commands/init.mjs index 585b54ff6..8663c6d9a 100644 --- a/src/commands/init.mjs +++ b/src/commands/init.mjs @@ -143,7 +143,7 @@ export class InitCommand extends BaseCommand { * Return Yargs command definition for 'init' command * @param initCmd an instance of InitCommand */ - static getCommandDefinition (initCmd: InitCommand) { + static getCommandDefinition (initCmd) { if (!initCmd || !(initCmd instanceof InitCommand)) { throw new FullstackTestingError('Invalid InitCommand instance') } diff --git a/src/commands/mirror_node.mjs b/src/commands/mirror_node.mjs index 3653c484f..46adc4c06 100644 --- a/src/commands/mirror_node.mjs +++ b/src/commands/mirror_node.mjs @@ -32,7 +32,7 @@ export class MirrorNodeCommand extends BaseCommand { this.profileManager = opts.profileManager } - async prepareValuesArg (valuesFile: string, deployHederaExplorer:boolean) { + async prepareValuesArg (valuesFile, deployHederaExplorer) { let valuesArg = '' if (valuesFile) { valuesArg += this.prepareValuesFiles(valuesFile) @@ -279,7 +279,7 @@ export class MirrorNodeCommand extends BaseCommand { * Return Yargs command definition for 'mirror-mirror-node' command * @param mirrorNodeCmd an instance of NodeCommand */ - static getCommandDefinition (mirrorNodeCmd: MirrorNodeCommand) { + static getCommandDefinition (mirrorNodeCmd) { if (!mirrorNodeCmd || !(mirrorNodeCmd instanceof MirrorNodeCommand)) { throw new IllegalArgumentError('Invalid MirrorNodeCommand instance', mirrorNodeCmd) } diff --git a/src/commands/network.mjs b/src/commands/network.mjs index 7cb892a0d..30c9c291d 100644 --- a/src/commands/network.mjs +++ b/src/commands/network.mjs @@ -33,8 +33,8 @@ export class NetworkCommand extends BaseCommand { this.profileManager = opts.profileManager } - getTlsValueArguments (tlsClusterIssuerType: string, enableHederaExplorerTls: boolean, namespace: string, - hederaExplorerTlsLoadBalancerIp: string, hederaExplorerTlsHostName: string) { + getTlsValueArguments (tlsClusterIssuerType, enableHederaExplorerTls, namespace, + hederaExplorerTlsLoadBalancerIp, hederaExplorerTlsHostName) { let valuesArg = '' if (enableHederaExplorerTls) { @@ -392,7 +392,7 @@ export class NetworkCommand extends BaseCommand { return true } - static getCommandDefinition (networkCmd: NetworkCommand) { + static getCommandDefinition (networkCmd) { if (!networkCmd || !(networkCmd instanceof NetworkCommand)) { throw new MissingArgumentError('An instance of NetworkCommand is required', networkCmd) } diff --git a/src/commands/node.mjs b/src/commands/node.mjs index 613a450ba..d53c57f39 100644 --- a/src/commands/node.mjs +++ b/src/commands/node.mjs @@ -61,7 +61,7 @@ export class NodeCommand extends BaseCommand { this._portForwards = [] } - async checkNetworkNodePod (namespace: string, nodeId: string) { + async checkNetworkNodePod (namespace, nodeId) { nodeId = nodeId.trim() const podName = Templates.renderNetworkPodName(nodeId) @@ -77,7 +77,7 @@ export class NodeCommand extends BaseCommand { } } - async checkNetworkNodeStarted (nodeId: string, maxAttempt: number = 100, status: string = 'ACTIVE') { + async checkNetworkNodeStarted (nodeId, maxAttempt = 100, status = 'ACTIVE') { nodeId = nodeId.trim() const podName = Templates.renderNetworkPodName(nodeId) const logfilePath = `${constants.HEDERA_HAPI_PATH}/logs/hgcaa.log` @@ -176,10 +176,9 @@ export class NodeCommand extends BaseCommand { * @return a list of subtasks * @private */ - _nodeGossipKeysTaskList (keyFormat: string, nodeIds: Array, keysDir: string, curDate = new Date()) { - // check if nodeIds is an array of strings + _nodeGossipKeysTaskList (keyFormat, nodeIds, keysDir, curDate = new Date()) { if (!Array.isArray(nodeIds) || !nodeIds.every((nodeId) => typeof nodeId === 'string')) { - throw new FullstackTestingError('nodeIds must be an array of strings') + throw new IllegalArgumentError('nodeIds must be an array of strings') } const self = this const subTasks = [] @@ -278,7 +277,7 @@ export class NodeCommand extends BaseCommand { * @return return a list of subtasks * @private */ - _nodeTlsKeyTaskList (nodeIds: Array, keysDir: string, curDate = new Date()) { + _nodeTlsKeyTaskList (nodeIds, keysDir, curDate = new Date()) { // check if nodeIds is an array of strings if (!Array.isArray(nodeIds) || !nodeIds.every((nodeId) => typeof nodeId === 'string')) { throw new FullstackTestingError('nodeIds must be an array of strings') diff --git a/src/core/account_manager.mjs b/src/core/account_manager.mjs index f44232279..7f3be0b63 100644 --- a/src/core/account_manager.mjs +++ b/src/core/account_manager.mjs @@ -31,7 +31,7 @@ import { Status, TransferTransaction } from '@hashgraph/sdk' -import { FullstackTestingError, MissingArgumentError } from './errors.mjs' +import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from './errors.mjs' import { Templates } from './templates.mjs' import ip from 'ip' @@ -520,7 +520,12 @@ export class AccountManager { * @param hbarAmount the amount of HBAR * @returns {Promise} if the transaction was successfully posted */ - async transferAmount (fromAccountId: AccountId, toAccountId: AccountId, hbarAmount:number) { + async transferAmount (fromAccountId, toAccountId, hbarAmount) { + // check if fromAccountId is AccountId, throw error if not + if (!(fromAccountId instanceof AccountId)) { + throw new IllegalArgumentError('fromAccountId is not an instance of AccountId') + } + try { const transaction = new TransferTransaction() .addHbarTransfer(fromAccountId, new Hbar(-1 * hbarAmount)) diff --git a/src/core/chart_manager.mjs b/src/core/chart_manager.mjs index 924ccb432..52c91c390 100644 --- a/src/core/chart_manager.mjs +++ b/src/core/chart_manager.mjs @@ -60,7 +60,7 @@ export class ChartManager { * List available clusters * @returns {Promise} */ - async getInstalledCharts (namespaceName: string) { + async getInstalledCharts (namespaceName) { try { return await this.helm.list(`-n ${namespaceName}`, '--no-headers | awk \'{print $1 " [" $9"]"}\'') } catch (e) { From 18bad8bd26612926d393e854ee5f0f0d1556f733 Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Tue, 9 Apr 2024 15:52:05 -0500 Subject: [PATCH 04/10] code check Signed-off-by: Jeffrey Tang --- src/commands/account.mjs | 3 +-- src/commands/cluster.mjs | 4 ++-- src/commands/init.mjs | 4 ++-- src/commands/network.mjs | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/commands/account.mjs b/src/commands/account.mjs index 47a597acd..37743ef98 100644 --- a/src/commands/account.mjs +++ b/src/commands/account.mjs @@ -21,8 +21,7 @@ import { flags } from './index.mjs' import { Listr } from 'listr2' import * as prompts from './prompts.mjs' import { constants } from '../core/index.mjs' -import { AccountInfo, HbarUnit, PrivateKey } from '@hashgraph/sdk' -import AccountId from '@hashgraph/sdk/lib/account/AccountId.js' +import { AccountId, AccountInfo, HbarUnit, PrivateKey } from '@hashgraph/sdk' export class AccountCommand extends BaseCommand { constructor (opts, systemAccounts = constants.SYSTEM_ACCOUNTS) { diff --git a/src/commands/cluster.mjs b/src/commands/cluster.mjs index f8cd2dd66..e8e81f00f 100644 --- a/src/commands/cluster.mjs +++ b/src/commands/cluster.mjs @@ -16,7 +16,7 @@ */ import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import { Listr } from 'listr2' -import { FullstackTestingError } from '../core/errors.mjs' +import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' import * as flags from './flags.mjs' import { BaseCommand } from './base.mjs' import chalk from 'chalk' @@ -221,7 +221,7 @@ export class ClusterCommand extends BaseCommand { */ static getCommandDefinition (clusterCmd) { if (!clusterCmd || !(clusterCmd instanceof ClusterCommand)) { - throw new FullstackTestingError('Invalid ClusterCommand instance') + throw new IllegalArgumentError('Invalid ClusterCommand instance') } return { command: 'cluster', diff --git a/src/commands/init.mjs b/src/commands/init.mjs index 8663c6d9a..0d8143ba9 100644 --- a/src/commands/init.mjs +++ b/src/commands/init.mjs @@ -20,7 +20,7 @@ import { BaseCommand } from './base.mjs' import * as core from '../core/index.mjs' import { constants } from '../core/index.mjs' import * as fs from 'fs' -import { FullstackTestingError } from '../core/errors.mjs' +import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' import * as flags from './flags.mjs' import chalk from 'chalk' @@ -145,7 +145,7 @@ export class InitCommand extends BaseCommand { */ static getCommandDefinition (initCmd) { if (!initCmd || !(initCmd instanceof InitCommand)) { - throw new FullstackTestingError('Invalid InitCommand instance') + throw new IllegalArgumentError('Invalid InitCommand') } return { command: 'init', diff --git a/src/commands/network.mjs b/src/commands/network.mjs index 30c9c291d..9ec1ac03f 100644 --- a/src/commands/network.mjs +++ b/src/commands/network.mjs @@ -17,7 +17,7 @@ import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import chalk from 'chalk' import { Listr } from 'listr2' -import { FullstackTestingError, MissingArgumentError } from '../core/errors.mjs' +import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from '../core/errors.mjs' import { BaseCommand } from './base.mjs' import * as flags from './flags.mjs' import { constants } from '../core/index.mjs' @@ -394,7 +394,7 @@ export class NetworkCommand extends BaseCommand { static getCommandDefinition (networkCmd) { if (!networkCmd || !(networkCmd instanceof NetworkCommand)) { - throw new MissingArgumentError('An instance of NetworkCommand is required', networkCmd) + throw new IllegalArgumentError('An instance of NetworkCommand is required', networkCmd) } return { command: 'network', From 26009953672c7bcf82f4ab97a7ee7cacd5c29d98 Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Tue, 9 Apr 2024 19:06:50 -0500 Subject: [PATCH 05/10] code check Signed-off-by: Jeffrey Tang --- src/commands/account.mjs | 6 +----- src/commands/node.mjs | 3 +++ src/commands/prompts.mjs | 5 ++++- src/commands/relay.mjs | 3 +++ src/core/dependency_managers/dependency_manager.mjs | 1 + src/core/dependency_managers/helm_dependency_manager.mjs | 3 ++- src/core/dependency_managers/keytool_dependency_manager.mjs | 3 ++- src/core/helm.mjs | 2 ++ src/core/keytool.mjs | 2 ++ 9 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/commands/account.mjs b/src/commands/account.mjs index 37743ef98..4c0813162 100644 --- a/src/commands/account.mjs +++ b/src/commands/account.mjs @@ -21,7 +21,7 @@ import { flags } from './index.mjs' import { Listr } from 'listr2' import * as prompts from './prompts.mjs' import { constants } from '../core/index.mjs' -import { AccountId, AccountInfo, HbarUnit, PrivateKey } from '@hashgraph/sdk' +import { AccountInfo, HbarUnit, PrivateKey } from '@hashgraph/sdk' export class AccountCommand extends BaseCommand { constructor (opts, systemAccounts = constants.SYSTEM_ACCOUNTS) { @@ -97,10 +97,6 @@ export class AccountCommand extends BaseCommand { } async transferAmountFromOperator (toAccountId, amount) { - if (!(toAccountId instanceof AccountId)) { - throw new IllegalArgumentError('toAccountId must be an instance of AccountId', toAccountId) - } - return await this.accountManager.transferAmount(constants.TREASURY_ACCOUNT_ID, toAccountId, amount) } diff --git a/src/commands/node.mjs b/src/commands/node.mjs index d53c57f39..1e12d64d3 100644 --- a/src/commands/node.mjs +++ b/src/commands/node.mjs @@ -908,6 +908,9 @@ export class NodeCommand extends BaseCommand { * @param nodeCmd an instance of NodeCommand */ static getCommandDefinition (nodeCmd) { + if (!nodeCmd || !(nodeCmd instanceof NodeCommand)) { + throw new IllegalArgumentError('An instance of NodeCommand is required', nodeCmd) + } return { command: 'node', desc: 'Manage Hedera platform node in fullstack testing network', diff --git a/src/commands/prompts.mjs b/src/commands/prompts.mjs index 44b1a94a6..93000d144 100644 --- a/src/commands/prompts.mjs +++ b/src/commands/prompts.mjs @@ -17,7 +17,7 @@ import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import fs from 'fs' import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' -import { constants } from '../core/index.mjs' +import { ConfigManager, constants } from '../core/index.mjs' import * as flags from './flags.mjs' import * as helpers from '../core/helpers.mjs' @@ -451,6 +451,9 @@ export function getPromptMap () { * @return {Promise} */ export async function execute (task, configManager, flagList = []) { + if (!configManager || !(configManager instanceof ConfigManager)) { + throw new IllegalArgumentError('an instance of ConfigManager is required') + } const prompts = getPromptMap() for (const flag of flagList) { if (!prompts.has(flag.name)) { diff --git a/src/commands/relay.mjs b/src/commands/relay.mjs index 515ec3659..9605407cc 100644 --- a/src/commands/relay.mjs +++ b/src/commands/relay.mjs @@ -258,6 +258,9 @@ export class RelayCommand extends BaseCommand { } static getCommandDefinition (relayCmd) { + if (!relayCmd || !(relayCmd instanceof RelayCommand)) { + throw new MissingArgumentError('An instance of RelayCommand is required', relayCmd) + } return { command: 'relay', desc: 'Manage JSON RPC relays in fullstack testing network', diff --git a/src/core/dependency_managers/dependency_manager.mjs b/src/core/dependency_managers/dependency_manager.mjs index 0129f9bbe..aa7cc21c1 100644 --- a/src/core/dependency_managers/dependency_manager.mjs +++ b/src/core/dependency_managers/dependency_manager.mjs @@ -20,6 +20,7 @@ import { ShellRunner } from '../shell_runner.mjs' export class DependencyManager extends ShellRunner { constructor (logger, depManagerMap) { + if (!logger) throw new MissingArgumentError('an instance of core/Logger is required', logger) super(logger) if (!depManagerMap) throw new MissingArgumentError('A map of dependency managers are required') this.depManagerMap = depManagerMap diff --git a/src/core/dependency_managers/helm_dependency_manager.mjs b/src/core/dependency_managers/helm_dependency_manager.mjs index ea3890573..f0fa74560 100644 --- a/src/core/dependency_managers/helm_dependency_manager.mjs +++ b/src/core/dependency_managers/helm_dependency_manager.mjs @@ -18,7 +18,7 @@ import fs from 'fs' import os from 'os' import path from 'path' import * as util from 'util' -import { MissingArgumentError } from '../errors.mjs' +import { IllegalArgumentError, MissingArgumentError } from '../errors.mjs' import * as helpers from '../helpers.mjs' import { constants, Templates } from '../index.mjs' import * as version from '../../../version.mjs' @@ -50,6 +50,7 @@ export class HelmDependencyManager extends ShellRunner { if (!downloader) throw new MissingArgumentError('An instance of core/PackageDownloader is required') if (!zippy) throw new MissingArgumentError('An instance of core/Zippy is required') + if (!logger) throw new IllegalArgumentError('an instance of core/Logger is required', logger) if (!installationDir) throw new MissingArgumentError('installation directory is required') this.downloader = downloader diff --git a/src/core/dependency_managers/keytool_dependency_manager.mjs b/src/core/dependency_managers/keytool_dependency_manager.mjs index 49648eb84..0ad451079 100644 --- a/src/core/dependency_managers/keytool_dependency_manager.mjs +++ b/src/core/dependency_managers/keytool_dependency_manager.mjs @@ -19,7 +19,7 @@ import os from 'os' import path from 'path' import * as semver from 'semver' import * as util from 'util' -import { MissingArgumentError, FullstackTestingError } from '../errors.mjs' +import { MissingArgumentError, FullstackTestingError, IllegalArgumentError } from '../errors.mjs' import * as helpers from '../helpers.mjs' import { constants, Keytool, Templates } from '../index.mjs' import * as version from '../../../version.mjs' @@ -43,6 +43,7 @@ export class KeytoolDependencyManager extends ShellRunner { if (!downloader) throw new MissingArgumentError('An instance of core/PackageDownloader is required') if (!zippy) throw new MissingArgumentError('An instance of core/Zippy is required') + if (!logger) throw new IllegalArgumentError('an instance of core/Logger is required', logger) if (!installationDir) throw new MissingArgumentError('installation directory is required') this.downloader = downloader diff --git a/src/core/helm.mjs b/src/core/helm.mjs index ea6ab13ac..b0475be35 100644 --- a/src/core/helm.mjs +++ b/src/core/helm.mjs @@ -18,9 +18,11 @@ import os from 'os' import { constants } from './index.mjs' import { ShellRunner } from './shell_runner.mjs' import { Templates } from './templates.mjs' +import { IllegalArgumentError } from './errors.mjs' export class Helm extends ShellRunner { constructor (logger, osPlatform = os.platform()) { + if (!logger) throw new IllegalArgumentError('an instance of core/Logger is required', logger) super(logger) this.osPlatform = osPlatform this.helmPath = Templates.installationPath(constants.HELM, this.osPlatform) diff --git a/src/core/keytool.mjs b/src/core/keytool.mjs index fed06bbcd..97ffb32b0 100644 --- a/src/core/keytool.mjs +++ b/src/core/keytool.mjs @@ -18,9 +18,11 @@ import os from 'os' import { constants } from './index.mjs' import { ShellRunner } from './shell_runner.mjs' import { Templates } from './templates.mjs' +import { MissingArgumentError } from '"./errors.mjs' export class Keytool extends ShellRunner { constructor (logger, osPlatform = os.platform()) { + if (!logger) throw new MissingArgumentError('an instance of core/Logger is required', logger) super(logger) this.osPlatform = osPlatform this.keytoolPath = Templates.installationPath(constants.KEYTOOL, this.osPlatform) From b36beebcb15b0a9b52c7ef54b0b7eec9cfcb7118 Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Tue, 9 Apr 2024 19:20:48 -0500 Subject: [PATCH 06/10] fix typo Signed-off-by: Jeffrey Tang --- src/core/keytool.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/keytool.mjs b/src/core/keytool.mjs index 97ffb32b0..5860c02fd 100644 --- a/src/core/keytool.mjs +++ b/src/core/keytool.mjs @@ -18,7 +18,7 @@ import os from 'os' import { constants } from './index.mjs' import { ShellRunner } from './shell_runner.mjs' import { Templates } from './templates.mjs' -import { MissingArgumentError } from '"./errors.mjs' +import { MissingArgumentError } from './errors.mjs' export class Keytool extends ShellRunner { constructor (logger, osPlatform = os.platform()) { From 374c2a1cd3323c9e0b70e351959908bbcbf5d8dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 00:26:45 +0000 Subject: [PATCH 07/10] auto update README.md --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1cc645e4c..7ebb7925f 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ You can now use your cluster with: kubectl cluster-info --context kind-solo -Thanks for using kind! 😊 +Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/ ``` You may now view pods in your cluster using `k9s -A` as below: @@ -178,9 +178,9 @@ Kubernetes Namespace : solo ✔ Clean up temp files ✔ Generate gossip keys ✔ Backup old files +✔ TLS key for node: node1 ✔ TLS key for node: node2 ✔ TLS key for node: node0 -✔ TLS key for node: node1 ✔ Generate gRPC TLS keys ✔ Finalize ``` @@ -259,8 +259,8 @@ Kubernetes Cluster : kind-solo Kubernetes Namespace : solo ********************************************************************************** ✔ Initialize -✔ Check network pod: node0 ✔ Check network pod: node1 +✔ Check network pod: node0 ✔ Check network pod: node2 ✔ Identify network pods ✔ Copy configuration files @@ -268,9 +268,9 @@ Kubernetes Namespace : solo ✔ Copy gRPC TLS keys to staging ✔ Prepare config.txt for the network ✔ Prepare staging directory -✔ Node: node0 ✔ Node: node2 ✔ Node: node1 +✔ Node: node0 ✔ Fetch platform software into network nodes ✔ Copy Gossip keys ✔ Copy Gossip keys @@ -282,11 +282,11 @@ Kubernetes Namespace : solo ✔ Copy configuration files ✔ Copy configuration files ✔ Set file permissions +✔ Node: node2 +✔ Set file permissions ✔ Node: node1 ✔ Set file permissions ✔ Node: node0 -✔ Set file permissions -✔ Node: node2 ✔ Setup network nodes ✔ Finalize ``` @@ -308,13 +308,13 @@ Kubernetes Cluster : kind-solo Kubernetes Namespace : solo ********************************************************************************** ✔ Initialize -✔ Check network pod: node1 ✔ Check network pod: node0 ✔ Check network pod: node2 +✔ Check network pod: node1 ✔ Identify network pods -✔ Start node: node1 ✔ Start node: node0 ✔ Start node: node2 +✔ Start node: node1 ✔ Starting nodes ✔ Check node: node0 ✔ Check node: node1 @@ -375,7 +375,7 @@ Kubernetes Namespace : solo *** Deployed Relays *** ------------------------------------------------------------------------------- - - fullstack-deployment [fullstack-deployment-0.24.2] + - fullstack-deployment [fullstack-deployment-0.24.3] - relay-node0-node1 [hedera-json-rpc-relay-0.26.0-SNAPSHOT] - relay-node0-node1-node2 [hedera-json-rpc-relay-0.26.0-SNAPSHOT] @@ -453,7 +453,7 @@ Kubernetes Namespace : solo *** Deployed Relays *** ------------------------------------------------------------------------------- - - fullstack-deployment [fullstack-deployment-0.24.2] + - fullstack-deployment [fullstack-deployment-0.24.3] - relay-node0-node1 [hedera-json-rpc-relay-0.26.0-SNAPSHOT] @@ -516,9 +516,9 @@ Kubernetes Namespace : solo ✔ Gossip pem key for node: node2 ✔ Generate gossip keys ✔ Backup old files -✔ TLS key for node: node0 ✔ TLS key for node: node1 ✔ TLS key for node: node2 +✔ TLS key for node: node0 ✔ Generate gRPC TLS keys ✔ Finalize ``` From 1c533b5158df362ff7dc7aee42496f882d18950c Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Wed, 10 Apr 2024 09:29:09 -0500 Subject: [PATCH 08/10] fix typo Signed-off-by: Jeffrey Tang --- src/core/account_manager.mjs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/core/account_manager.mjs b/src/core/account_manager.mjs index 7f3be0b63..d5bced87e 100644 --- a/src/core/account_manager.mjs +++ b/src/core/account_manager.mjs @@ -521,11 +521,6 @@ export class AccountManager { * @returns {Promise} if the transaction was successfully posted */ async transferAmount (fromAccountId, toAccountId, hbarAmount) { - // check if fromAccountId is AccountId, throw error if not - if (!(fromAccountId instanceof AccountId)) { - throw new IllegalArgumentError('fromAccountId is not an instance of AccountId') - } - try { const transaction = new TransferTransaction() .addHbarTransfer(fromAccountId, new Hbar(-1 * hbarAmount)) From 5ccd55586e32812e4b2deae216d8c96555af827f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:34:45 +0000 Subject: [PATCH 09/10] auto update README.md --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8bfaf86c9..84631b5cc 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ You can now use your cluster with: kubectl cluster-info --context kind-solo -Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/ +Thanks for using kind! 😊 ``` You may now view pods in your cluster using `k9s -A` as below: @@ -178,9 +178,9 @@ Kubernetes Namespace : solo ✔ Clean up temp files ✔ Generate gossip keys ✔ Backup old files -✔ TLS key for node: node1 -✔ TLS key for node: node2 ✔ TLS key for node: node0 +✔ TLS key for node: node2 +✔ TLS key for node: node1 ✔ Generate gRPC TLS keys ✔ Finalize ``` @@ -259,18 +259,18 @@ Kubernetes Cluster : kind-solo Kubernetes Namespace : solo ********************************************************************************** ✔ Initialize -✔ Check network pod: node1 ✔ Check network pod: node0 ✔ Check network pod: node2 +✔ Check network pod: node1 ✔ Identify network pods ✔ Copy configuration files ✔ Copy Gossip keys to staging ✔ Copy gRPC TLS keys to staging ✔ Prepare config.txt for the network ✔ Prepare staging directory -✔ Node: node2 ✔ Node: node1 ✔ Node: node0 +✔ Node: node2 ✔ Fetch platform software into network nodes ✔ Copy Gossip keys ✔ Copy Gossip keys @@ -282,11 +282,11 @@ Kubernetes Namespace : solo ✔ Copy configuration files ✔ Copy configuration files ✔ Set file permissions +✔ Node: node0 +✔ Set file permissions ✔ Node: node2 ✔ Set file permissions ✔ Node: node1 -✔ Set file permissions -✔ Node: node0 ✔ Setup network nodes ✔ Finalize ``` @@ -308,13 +308,13 @@ Kubernetes Cluster : kind-solo Kubernetes Namespace : solo ********************************************************************************** ✔ Initialize +✔ Check network pod: node1 ✔ Check network pod: node0 ✔ Check network pod: node2 -✔ Check network pod: node1 ✔ Identify network pods -✔ Start node: node0 -✔ Start node: node2 ✔ Start node: node1 +✔ Start node: node2 +✔ Start node: node0 ✔ Starting nodes ✔ Check node: node0 ✔ Check node: node1 @@ -516,9 +516,9 @@ Kubernetes Namespace : solo ✔ Gossip pem key for node: node2 ✔ Generate gossip keys ✔ Backup old files -✔ TLS key for node: node1 -✔ TLS key for node: node2 ✔ TLS key for node: node0 +✔ TLS key for node: node2 +✔ TLS key for node: node1 ✔ Generate gRPC TLS keys ✔ Finalize ``` @@ -579,6 +579,6 @@ Contributions are welcome. Please see the [contributing guide](https://github.co This project is governed by the [Contributor Covenant Code of Conduct](https://github.com/hashgraph/.github/blob/main/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code of conduct. -## License +## License [Apache License 2.0](LICENSE) From d77cfb1c5b14e1b9bd7df74d7b66aca68619718e Mon Sep 17 00:00:00 2001 From: Jeffrey Tang Date: Wed, 10 Apr 2024 09:58:22 -0500 Subject: [PATCH 10/10] no longer need Signed-off-by: Jeffrey Tang --- src/core/account_manager.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/account_manager.mjs b/src/core/account_manager.mjs index d5bced87e..983f57850 100644 --- a/src/core/account_manager.mjs +++ b/src/core/account_manager.mjs @@ -31,7 +31,7 @@ import { Status, TransferTransaction } from '@hashgraph/sdk' -import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from './errors.mjs' +import { FullstackTestingError, MissingArgumentError } from './errors.mjs' import { Templates } from './templates.mjs' import ip from 'ip'