Skip to content

Commit

Permalink
feat: add support for --force-port-forward as a top level flag (#1404)
Browse files Browse the repository at this point in the history
Signed-off-by: Lenin Mehedy <[email protected]>
  • Loading branch information
leninmehedy authored Feb 16, 2025
1 parent f3f7958 commit 5c18967
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 42 deletions.
8 changes: 6 additions & 2 deletions src/commands/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {IllegalArgumentError, SoloError} from '../core/errors.js';
import {Flags as flags} from './flags.js';
import {Listr} from 'listr2';
import * as constants from '../core/constants.js';
import * as helpers from '../core/helpers.js';
import {FREEZE_ADMIN_ACCOUNT} from '../core/constants.js';
import * as helpers from '../core/helpers.js';
import {sleep} from '../core/helpers.js';
import {type AccountManager} from '../core/account_manager.js';
import {type AccountId, AccountInfo, HbarUnit, NodeUpdateTransaction, PrivateKey} from '@hashgraph/sdk';
import {ListrLease} from '../core/lease/listr_lease.js';
Expand All @@ -18,7 +19,6 @@ import {Duration} from '../core/time/duration.js';
import {type NamespaceName} from '../core/kube/resources/namespace/namespace_name.js';
import {type DeploymentName} from '../core/config/remote/types.js';
import {Templates} from '../core/templates.js';
import {sleep} from '../core/helpers.js';
import {SecretType} from '../core/kube/resources/secret/secret_type.js';
import {Base64} from 'js-base64';

Expand Down Expand Up @@ -189,6 +189,7 @@ export class AccountCommand extends BaseCommand {
ctx.config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
);
},
},
Expand Down Expand Up @@ -409,6 +410,7 @@ export class AccountCommand extends BaseCommand {
ctx.config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
);

return ListrLease.newAcquireLeaseTask(lease, task);
Expand Down Expand Up @@ -489,6 +491,7 @@ export class AccountCommand extends BaseCommand {
config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
);

self.logger.debug('Initialized config', {config});
Expand Down Expand Up @@ -575,6 +578,7 @@ export class AccountCommand extends BaseCommand {
config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
);

self.logger.debug('Initialized config', {config});
Expand Down
12 changes: 12 additions & 0 deletions src/commands/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ export class Flags {
prompt: undefined,
};

static readonly forcePortForward: CommandFlag = {
constName: 'forcePortForward',
name: 'force-port-forward',
definition: {
describe: 'Force port forward to access the network services',
defaultValue: true, // always use local port-forwarding by default
type: 'boolean',
},
prompt: undefined,
};

// list of common flags across commands. command specific flags are defined in the command's module.
static readonly clusterRef: CommandFlag = {
constName: 'clusterRef',
Expand Down Expand Up @@ -2059,6 +2070,7 @@ export class Flags {
Flags.enableTimeout,
Flags.endpointType,
Flags.envoyIps,
Flags.forcePortForward,
Flags.generateEcdsaKey,
Flags.generateGossipKeys,
Flags.generateTlsKeys,
Expand Down
18 changes: 11 additions & 7 deletions src/commands/mirror_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ export class MirrorNodeCommand extends BaseCommand {
ctx.config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
ctx.config.clusterContext,
);
if (ctx.config.pinger) {
Expand Down Expand Up @@ -479,23 +480,25 @@ export class MirrorNodeCommand extends BaseCommand {
feesFileIdNum,
clusterRefs,
deployment,
this.configManager.getFlag<boolean>(flags.forcePortForward),
);
const exchangeRates = await this.accountManager.getFileContents(
namespace,
exchangeRatesFileIdNum,
clusterRefs,
deployment,
this.configManager.getFlag<boolean>(flags.forcePortForward),
);

const importFeesQuery = `INSERT INTO public.file_data(file_data, consensus_timestamp, entity_id,
transaction_type)
VALUES (decode('${fees}', 'hex'), ${timestamp + '000000'},
${feesFileIdNum}, 17);`;
transaction_type)
VALUES (decode('${fees}', 'hex'), ${timestamp + '000000'},
${feesFileIdNum}, 17);`;
const importExchangeRatesQuery = `INSERT INTO public.file_data(file_data, consensus_timestamp,
entity_id, transaction_type)
VALUES (decode('${exchangeRates}', 'hex'), ${
timestamp + '000001'
}, ${exchangeRatesFileIdNum}, 17);`;
entity_id, transaction_type)
VALUES (decode('${exchangeRates}', 'hex'), ${
timestamp + '000001'
}, ${exchangeRatesFileIdNum}, 17);`;
const sqlQuery = [importFeesQuery, importExchangeRatesQuery].join('\n');

// When useExternalDatabase flag is enabled, the query is not executed,
Expand Down Expand Up @@ -651,6 +654,7 @@ export class MirrorNodeCommand extends BaseCommand {
ctx.config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
ctx.config.clusterContext,
);
return ListrLease.newAcquireLeaseTask(lease, task);
Expand Down
9 changes: 7 additions & 2 deletions src/commands/node/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {IllegalArgumentError, MissingArgumentError, SoloError} from '../../core/
import path from 'path';
import fs from 'fs';
import crypto from 'crypto';
import * as helpers from '../../core/helpers.js';
import {
addDebugOptions,
getNodeAccountMap,
Expand Down Expand Up @@ -67,7 +68,6 @@ import {PodRef} from '../../core/kube/resources/pod/pod_ref.js';
import {ContainerRef} from '../../core/kube/resources/container/container_ref.js';
import {NetworkNodes} from '../../core/network_nodes.js';
import {container} from 'tsyringe-neo';
import * as helpers from '../../core/helpers.js';
import {type Optional} from '../../types/index.js';
import {type DeploymentName} from '../../core/config/remote/types.js';
import {ConsensusNode} from '../../core/model/consensus_node.js';
Expand Down Expand Up @@ -562,7 +562,12 @@ export class NodeCommandTasks {
) {
try {
const deploymentName = this.configManager.getFlag<DeploymentName>(flags.deployment);
await this.accountManager.loadNodeClient(namespace, this.parent.getClusterRefs(), deploymentName);
await this.accountManager.loadNodeClient(
namespace,
this.parent.getClusterRefs(),
deploymentName,
this.configManager.getFlag<boolean>(flags.forcePortForward),
);
const client = this.accountManager._nodeClient;
const treasuryKey = await this.accountManager.getTreasuryAccountKeys(namespace);
const treasuryPrivateKey = PrivateKey.fromStringED25519(treasuryKey.privateKey);
Expand Down
1 change: 1 addition & 0 deletions src/commands/relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export class RelayCommand extends BaseCommand {
ctx.config.namespace,
self.getClusterRefs(),
self.configManager.getFlag<DeploymentName>(flags.deployment),
self.configManager.getFlag<boolean>(flags.forcePortForward),
ctx.config.context,
);
config.valuesArg = await self.prepareValuesArg(
Expand Down
23 changes: 16 additions & 7 deletions src/core/account_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {PodRef} from './kube/resources/pod/pod_ref.js';
import {SecretType} from './kube/resources/secret/secret_type.js';
import {type V1Pod} from '@kubernetes/client-node';
import {InjectTokens} from './dependency_injection/inject_tokens.js';
import {type ClusterRef, type DeploymentName, type ClusterRefs} from './config/remote/types.js';
import {type ClusterRefs, type DeploymentName} from './config/remote/types.js';
import {type Service} from './kube/resources/service/service.js';
import {SoloService} from './model/solo_service.js';

Expand All @@ -55,6 +55,7 @@ const REJECTED = 'rejected';
@injectable()
export class AccountManager {
private _portForwards: ExtendedNetServer[];
private _forcePortForward: boolean = false;
public _nodeClient: Client | null;

constructor(
Expand Down Expand Up @@ -167,14 +168,16 @@ export class AccountManager {
/**
* loads and initializes the Node Client
* @param namespace - the namespace of the network
* @param clusterRefs
* @param deployment
* @param context
* @param clusterRefs - the cluster references to use
* @param deployment - k8 deployment name
* @param context - k8 context name
* @param forcePortForward - whether to force the port forward
*/
async loadNodeClient(
namespace: NamespaceName,
clusterRefs?: ClusterRefs,
deployment?: DeploymentName,
forcePortForward?: boolean,
context?: Optional<string>,
) {
try {
Expand All @@ -185,7 +188,7 @@ export class AccountManager {
this.logger.debug(
`refreshing node client: [!this._nodeClient=${!this._nodeClient}, this._nodeClient.isClientShutDown=${this._nodeClient?.isClientShutDown}]`,
);
await this.refreshNodeClient(namespace, undefined, clusterRefs, deployment, context);
await this.refreshNodeClient(namespace, undefined, clusterRefs, deployment, context, forcePortForward);
} else {
try {
if (!constants.SKIP_NODE_PING) {
Expand All @@ -212,16 +215,21 @@ export class AccountManager {
* @param [clusterRefs]
* @param [deployment]
* @param [context]
* @param forcePortForward - whether to force the port forward
*/
async refreshNodeClient(
namespace: NamespaceName,
skipNodeAlias?: NodeAlias,
clusterRefs?: ClusterRefs,
deployment?: DeploymentName,
context?: Optional<string>,
forcePortForward?: boolean,
) {
try {
await this.close();
if (forcePortForward !== undefined) {
this._forcePortForward = forcePortForward;
}

const treasuryAccountInfo = await this.getTreasuryAccountKeys(namespace, context);
const networkNodeServicesMap = await this.getNodeServiceMap(namespace, clusterRefs, deployment);
Expand Down Expand Up @@ -249,7 +257,7 @@ export class AccountManager {
* @returns whether to use the local host port forward
*/
private shouldUseLocalHostPortForward(networkNodeServices: NetworkNodeServices) {
return !networkNodeServices.haProxyLoadBalancerIp;
return this._forcePortForward || !networkNodeServices.haProxyLoadBalancerIp;
}

/**
Expand Down Expand Up @@ -974,8 +982,9 @@ export class AccountManager {
fileNum: number,
clusterRefs?: ClusterRefs,
deployment?: DeploymentName,
forcePortForward?: boolean,
) {
await this.loadNodeClient(namespace, clusterRefs, deployment);
await this.loadNodeClient(namespace, clusterRefs, deployment, forcePortForward);
const client = this._nodeClient;
const fileId = FileId.fromString(`0.0.${fileNum}`);
const queryFees = new FileContentsQuery().setFileId(fileId);
Expand Down
32 changes: 15 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,23 +144,21 @@ export function main(argv: any) {
return argv;
};

return (
yargs(hideBin(argv))
.scriptName('')
.usage('Usage:\n solo <command> [options]')
.alias('h', 'help')
.alias('v', 'version')
// @ts-ignore
.command(commands.Initialize(opts))
.strict()
// @ts-ignore
.option(flags.devMode.name, flags.devMode.definition)
.wrap(120)
.demand(1, 'Select a command')
// @ts-ignore
.middleware([processArguments, loadRemoteConfig], false) // applyBeforeValidate = false as otherwise middleware is called twice
.parse()
);
const rootCmd = yargs(hideBin(argv))
.scriptName('')
.usage('Usage:\n solo <command> [options]')
.alias('h', 'help')
.alias('v', 'version')
// @ts-ignore
.command(commands.Initialize(opts))
.strict()
.demand(1, 'Select a command')
// @ts-ignore
.middleware([processArguments, loadRemoteConfig], false); // applyBeforeValidate = false as otherwise middleware is called twice

// set root level flags
flags.setCommandFlags(rootCmd, ...[flags.devMode, flags.forcePortForward]);
return rootCmd.parse();
} catch (e: Error | any) {
logger.showUserError(e);
process.exit(1);
Expand Down
22 changes: 19 additions & 3 deletions test/e2e/commands/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const testName = 'account-cmd-e2e';
const namespace: NamespaceName = NamespaceName.of(testName);
const testSystemAccounts = [[3, 5]];
const argv = getDefaultArgv(namespace);
argv[flags.forcePortForward.name] = true;
argv[flags.namespace.name] = namespace.name;
argv[flags.releaseTag.name] = HEDERA_PLATFORM_VERSION_TAG;
argv[flags.nodeAliasesUnparsed.name] = 'node1,node2';
Expand Down Expand Up @@ -107,7 +108,12 @@ e2eTestSuite(testName, argv, undefined, undefined, undefined, undefined, undefin
before(async function () {
this.timeout(Duration.ofSeconds(20).toMillis());
const clusterRefs = accountCmd.getClusterRefs();
await accountManager.loadNodeClient(namespace, clusterRefs, argv[flags.deployment.name]);
await accountManager.loadNodeClient(
namespace,
clusterRefs,
argv[flags.deployment.name],
argv[flags.forcePortForward.name],
);
});

after(async function () {
Expand Down Expand Up @@ -298,7 +304,12 @@ e2eTestSuite(testName, argv, undefined, undefined, undefined, undefined, undefin
);

const clusterRefs = accountCmd.getClusterRefs();
await accountManager.loadNodeClient(namespace, clusterRefs, argv[flags.deployment.name]);
await accountManager.loadNodeClient(
namespace,
clusterRefs,
argv[flags.deployment.name],
argv[flags.forcePortForward.name],
);
const accountAliasInfo = await accountManager.accountInfoQuery(newAccountInfo.accountAlias);
expect(accountAliasInfo).not.to.be.null;
} catch (e) {
Expand All @@ -325,7 +336,12 @@ e2eTestSuite(testName, argv, undefined, undefined, undefined, undefined, undefin
it('Create new account', async () => {
try {
const clusterRefs = accountCmd.getClusterRefs();
await accountManager.loadNodeClient(namespace, clusterRefs, argv[flags.deployment.name]);
await accountManager.loadNodeClient(
namespace,
clusterRefs,
argv[flags.deployment.name],
argv[flags.forcePortForward.name],
);
const privateKey = PrivateKey.generate();
const amount = 100;

Expand Down
10 changes: 8 additions & 2 deletions test/e2e/commands/mirror_node.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* SPDX-License-Identifier: Apache-2.0
*/
import {it, describe, after, before, afterEach} from 'mocha';
import {after, afterEach, before, describe, it} from 'mocha';
import {expect} from 'chai';

import {Flags as flags} from '../../../src/commands/flags.js';
Expand Down Expand Up @@ -35,6 +35,7 @@ const namespace = NamespaceName.of(testName);
const argv = getDefaultArgv(namespace);
argv[flags.namespace.name] = namespace.name;
argv[flags.releaseTag.name] = HEDERA_PLATFORM_VERSION_TAG;
argv[flags.forcePortForward.name] = true;

argv[flags.nodeAliasesUnparsed.name] = 'node1'; // use a single node to reduce resource during e2e tests
argv[flags.generateGossipKeys.name] = true;
Expand Down Expand Up @@ -115,7 +116,12 @@ e2eTestSuite(testName, argv, undefined, undefined, undefined, undefined, undefin

it('mirror node API should be running', async () => {
const clusterRefs: ClusterRefs = mirrorNodeCmd.getClusterRefs();
await accountManager.loadNodeClient(namespace, clusterRefs, argv[flags.deployment.name]);
await accountManager.loadNodeClient(
namespace,
clusterRefs,
argv[flags.deployment.name],
argv[flags.forcePortForward.name],
);
try {
// find hedera explorer pod
const pods: V1Pod[] = await k8Factory
Expand Down
Loading

0 comments on commit 5c18967

Please sign in to comment.