Skip to content

Commit

Permalink
feat(cli): reduce redundancy on context to cluster flags in command `…
Browse files Browse the repository at this point in the history
…deployment create` (#1156)

Signed-off-by: instamenta <[email protected]>
  • Loading branch information
instamenta authored Jan 24, 2025
1 parent 80176a3 commit 4ab4dd5
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 109 deletions.
2 changes: 1 addition & 1 deletion src/commands/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export abstract class BaseCommand extends ShellRunner {
protected readonly depManager: DependencyManager;
protected readonly leaseManager: LeaseManager;
protected readonly _configMaps = new Map<string, any>();
protected readonly localConfig: LocalConfig;
public readonly localConfig: LocalConfig;
protected readonly remoteConfigManager: RemoteConfigManager;

constructor(opts: Opts) {
Expand Down
8 changes: 7 additions & 1 deletion src/commands/cluster/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ export class ClusterCommandTasks {
// If one or more contexts are provided, use the first one
if (contexts.length) {
selectedContext = contexts[0];

if (clusters.length) {
selectedCluster = clusters[0];
} else if (localConfig.deployments[deploymentName]) {
selectedCluster = localConfig.deployments[deploymentName].clusters[0];
}
}

// If one or more clusters are provided, use the first one to determine the context
Expand Down Expand Up @@ -335,7 +341,7 @@ export class ClusterCommandTasks {

const connectionValid = await this.parent.getK8().testClusterConnection(selectedContext, selectedCluster);
if (!connectionValid) {
throw new SoloError(ErrorMessages.INVALID_CONTEXT_FOR_CLUSTER(selectedContext));
throw new SoloError(ErrorMessages.INVALID_CONTEXT_FOR_CLUSTER(selectedContext, selectedCluster));
}
this.parent.getK8().setCurrentContext(selectedContext);
this.parent.getConfigManager().setFlag(flags.context, selectedContext);
Expand Down
25 changes: 9 additions & 16 deletions src/commands/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@ import {SoloError} from '../core/errors.js';
import {BaseCommand} from './base.js';
import {Flags as flags} from './flags.js';
import * as constants from '../core/constants.js';
import {Templates} from '../core/templates.js';
import chalk from 'chalk';
import {ListrRemoteConfig} from '../core/config/remote/listr_config_tasks.js';
import {ClusterCommandTasks} from './cluster/tasks.js';
import type {Namespace} from '../core/config/remote/types.js';
import type {ContextClusterStructure} from '../types/config_types.js';
import type {CommandFlag} from '../types/flag_types.js';
import type {CommandBuilder} from '../types/aliases.js';
import type {Opts} from '../types/command_types.js';
import type {SoloListrTask} from '../types/index.js';
import type {Opts} from '../types/command_types.js';

export class DeploymentCommand extends BaseCommand {
readonly tasks: ClusterCommandTasks;
Expand All @@ -44,9 +42,9 @@ export class DeploymentCommand extends BaseCommand {
flags.quiet,
flags.context,
flags.namespace,
flags.clusterName,
flags.userEmailAddress,
flags.deploymentClusters,
flags.contextClusterUnparsed,
];
}

Expand All @@ -56,9 +54,8 @@ export class DeploymentCommand extends BaseCommand {
interface Config {
context: string;
namespace: Namespace;
contextClusterUnparsed: string;
contextCluster: ContextClusterStructure;
}

interface Context {
config: Config;
}
Expand All @@ -71,19 +68,12 @@ export class DeploymentCommand extends BaseCommand {
self.configManager.update(argv);
self.logger.debug('Updated config with argv', {config: self.configManager.config});

await self.configManager.executePrompt(task, [
flags.contextClusterUnparsed,
flags.namespace,
flags.deploymentClusters,
]);
await self.configManager.executePrompt(task, [flags.namespace]);

ctx.config = {
contextClusterUnparsed: self.configManager.getFlag<string>(flags.contextClusterUnparsed),
namespace: self.configManager.getFlag<Namespace>(flags.namespace),
} as Config;

ctx.config.contextCluster = Templates.parseContextCluster(ctx.config.contextClusterUnparsed);

self.logger.debug('Prepared config', {config: ctx.config, cachedConfig: self.configManager.config});
},
},
Expand Down Expand Up @@ -112,13 +102,16 @@ export class DeploymentCommand extends BaseCommand {
task: async (ctx, task) => {
const subTasks: SoloListrTask<Context>[] = [];

for (const context of Object.keys(ctx.config.contextCluster)) {
const cluster = ctx.config.contextCluster[context];
for (const cluster of self.localConfig.deployments[ctx.config.namespace].clusters) {
const context = self.localConfig.clusterContextMapping?.[cluster];
if (!context) continue;

subTasks.push({
title: `Testing connection to cluster: ${chalk.cyan(cluster)}`,
task: async (_, task) => {
if (!(await self.k8.testClusterConnection(context, cluster))) {
task.title = `${task.title} - ${chalk.red('Cluster connection failed')}`;

throw new SoloError(`Cluster connection failed for: ${cluster}`);
}
},
Expand Down
22 changes: 0 additions & 22 deletions src/commands/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1576,27 +1576,6 @@ export class Flags {
prompt: undefined,
};

static readonly contextClusterUnparsed: CommandFlag = {
constName: 'contextClusterUnparsed',
name: 'context-cluster',
definition: {
describe:
'Context cluster mapping where context is key = value is cluster and comma delimited if more than one, ' +
'(e.g.: --context-cluster kind-solo=kind-solo,kind-solo-2=kind-solo-2)',
type: 'string',
},
prompt: async function promptContextCluster(task: ListrTaskWrapper<any, any, any>, input: any) {
return await Flags.promptText(
task,
input,
null,
'Enter context cluster mapping: ',
'context-cluster cannot be empty',
Flags.contextClusterUnparsed.name,
);
},
};

static readonly haproxyIps: CommandFlag = {
constName: 'haproxyIps',
name: 'haproxy-ips',
Expand Down Expand Up @@ -1725,7 +1704,6 @@ export class Flags {
Flags.clusterName,
Flags.clusterSetupNamespace,
Flags.context,
Flags.contextClusterUnparsed,
Flags.createAmount,
Flags.debugNodeAlias,
Flags.deletePvcs,
Expand Down
4 changes: 2 additions & 2 deletions src/commands/mirror_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ export class MirrorNodeCommand extends BaseCommand {
}

/** Removes the mirror node components from remote config. */
public removeMirrorNodeComponents(): SoloListrTask<object> {
public removeMirrorNodeComponents(): SoloListrTask<any> {
return {
title: 'Remove mirror node from remote config',
skip: (): boolean => !this.remoteConfigManager.isLoaded(),
Expand All @@ -583,7 +583,7 @@ export class MirrorNodeCommand extends BaseCommand {
}

/** Adds the mirror node components to remote config. */
public addMirrorNodeComponents(): SoloListrTask<{config: {namespace: Namespace}}> {
public addMirrorNodeComponents(): SoloListrTask<any> {
return {
title: 'Add mirror node to remote config',
skip: (): boolean => !this.remoteConfigManager.isLoaded(),
Expand Down
2 changes: 1 addition & 1 deletion src/commands/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ export class NetworkCommand extends BaseCommand {
}

/** Adds the consensus node, envoy and haproxy components to remote config. */
public addNodesAndProxies(): SoloListrTask<{config: {namespace: Namespace; nodeAliases: NodeAliases}}> {
public addNodesAndProxies(): SoloListrTask<any> {
return {
title: 'Add node and proxies to remote config',
skip: (): boolean => !this.remoteConfigManager.isLoaded(),
Expand Down
5 changes: 3 additions & 2 deletions src/core/config/local_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import {type K8} from '../k8.js';
import {splitFlagInput} from '../helpers.js';
import {inject, injectable} from 'tsyringe-neo';
import {patchInject} from '../container_helper.js';
import type {SoloListrTask, SoloListrTaskWrapper} from '../../types/index.js';
import type {SoloListrTask} from '../../types/index.js';
import type {AnyObject} from '../../types/aliases.js';

@injectable()
export class LocalConfig implements LocalConfigData {
Expand Down Expand Up @@ -168,7 +169,7 @@ export class LocalConfig implements LocalConfigData {
return {
title: 'Prompt local configuration',
skip: this.skipPromptTask,
task: async (_: any, task: SoloListrTaskWrapper<any>): Promise<void> => {
task: async (_, task): Promise<void> => {
if (self.configFileExists()) {
self.configManager.setFlag(flags.userEmailAddress, self.userEmailAddress);
}
Expand Down
23 changes: 13 additions & 10 deletions src/core/config/remote/listr_config_tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
* limitations under the License.
*
*/
import type {ListrTask} from 'listr2';
import chalk from 'chalk';
import type {BaseCommand} from '../../../commands/base.js';
import {type Cluster, type Context, type Namespace} from './types.js';
import type {Cluster, Context, Namespace} from './types.js';
import type {SoloListrTask} from '../../../types/index.js';
import type {AnyObject} from '../../../types/aliases.js';

/**
* Static class that handles all tasks related to remote config used by other commands.
Expand All @@ -38,10 +39,10 @@ export class ListrRemoteConfig {
* @param command - the BaseCommand object on which an action will be performed
* @param argv - used to update the last executed command and command history
*/
public static loadRemoteConfig(command: BaseCommand, argv: any): ListrTask<any, any, any> {
public static loadRemoteConfig(command: BaseCommand, argv: {_: string[]} & AnyObject): SoloListrTask<any> {
return {
title: 'Load remote config',
task: async (_, task): Promise<void> => {
task: async (): Promise<void> => {
await command.getRemoteConfigManager().loadAndValidate(argv);
},
};
Expand All @@ -59,10 +60,10 @@ export class ListrRemoteConfig {
cluster: Cluster,
context: Context,
namespace: Namespace,
): ListrTask<any, any, any> {
): SoloListrTask<any> {
return {
title: `Create remote config in cluster: ${cluster}`,
task: async (_, task): Promise<void> => {
title: `Create remote config in cluster: ${chalk.cyan(cluster)}`,
task: async (): Promise<void> => {
await command.getRemoteConfigManager().createAndValidate(cluster, context, namespace);
},
};
Expand All @@ -73,14 +74,16 @@ export class ListrRemoteConfig {
*
* @param command - the BaseCommand object on which an action will be performed
*/
public static createRemoteConfigInMultipleClusters(command: BaseCommand): ListrTask<any, any, any> {
public static createRemoteConfigInMultipleClusters(command: BaseCommand): SoloListrTask<any> {
return {
title: 'Create remoteConfig in clusters',
task: async (ctx, task) => {
const subTasks: SoloListrTask<Context>[] = [];

for (const context of Object.keys(ctx.config.contextCluster)) {
const cluster = ctx.config.contextCluster[context];
for (const cluster of command.localConfig.deployments[ctx.config.namespace].clusters) {
const context = command.localConfig.clusterContextMapping?.[cluster];
if (!context) continue;

subTasks.push(ListrRemoteConfig.createRemoteConfig(command, cluster, context, ctx.config.namespace));
}

Expand Down
8 changes: 4 additions & 4 deletions src/core/config/remote/remote_config_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ import {SoloLogger} from '../../logging.js';
import {ConfigManager} from '../../config_manager.js';
import {LocalConfig} from '../local_config.js';
import type {DeploymentStructure} from '../local_config_data.js';
import {type ContextClusterStructure} from '../../../types/config_types.js';
import {type EmptyContextConfig, type Optional, type SoloListrTask} from '../../../types/index.js';
import type {Optional} from '../../../types/index.js';
import type * as k8s from '@kubernetes/client-node';
import {StatusCodes} from 'http-status-codes';
import {inject, injectable} from 'tsyringe-neo';
import {patchInject} from '../../container_helper.js';
import {ErrorMessages} from '../../error_messages.js';
import {type AnyObject} from '../../../types/aliases.js';

interface ListrContext {
config: {contextCluster: ContextClusterStructure};
config: object;
}

/**
Expand Down Expand Up @@ -189,7 +189,7 @@ export class RemoteConfigManager {
*
* @param argv - arguments containing command input for historical reference.
*/
public async loadAndValidate(argv: {_: string[]}) {
public async loadAndValidate(argv: {_: string[]} & AnyObject) {
const self = this;
try {
self.setDefaultNamespaceIfNotSet();
Expand Down
32 changes: 1 addition & 31 deletions src/core/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import * as constants from './constants.js';
import {type AccountId} from '@hashgraph/sdk';
import type {IP, NodeAlias, NodeId, PodName} from '../types/aliases.js';
import {GrpcProxyTlsEnums} from './enumerations.js';
import {type ContextClusterStructure} from '../types/config_types.js';
import type {Cluster, Context, Namespace} from './config/remote/types.js';
import type {Namespace} from './config/remote/types.js';
import {HEDERA_PLATFORM_VERSION} from '../../version.js';

export class Templates {
Expand Down Expand Up @@ -228,35 +227,6 @@ export class Templates {
}
}

/**
* Parsed and validates the unparsed value of flag clusterMappings
*
* @param unparsed - value of flag clusterMappings
*/
public static parseContextCluster(unparsed: string): ContextClusterStructure {
const mapping = {};
const errorMessage =
'Invalid context in context-cluster, expected structure where context' +
' is key = value is cluster and comma delimited if more than one, ' +
'(e.g.: --context-cluster kind-solo=kind-solo,kind-solo-2=kind-solo-2)';

unparsed.split(',').forEach(data => {
const [context, cluster] = data.split('=') as [Context, Cluster];

if (!context || typeof context !== 'string') {
throw new SoloError(errorMessage, null, {data});
}

if (!cluster || typeof cluster !== 'string') {
throw new SoloError(errorMessage, null, {data});
}

mapping[context] = cluster;
});

return mapping;
}

public static renderEnvoyProxyName(nodeAlias: NodeAlias): string {
return `envoy-proxy-${nodeAlias}`;
}
Expand Down
19 changes: 0 additions & 19 deletions src/types/config_types.ts

This file was deleted.

0 comments on commit 4ab4dd5

Please sign in to comment.