Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): reduce redundancy on context to cluster flags in command deployment create #1156

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 22 additions & 31 deletions src/commands/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,22 @@
* limitations under the License.
*
*/
import {Listr, type ListrTaskWrapper} from 'listr2';
import {Listr} from 'listr2';
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 {RemoteConfigTasks} from '../core/config/remote/remote_config_tasks.js';
import {ListrLease} from '../core/lease/listr_lease.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 {CommandFlag} from '../types/flag_types.js';
import type {CommandBuilder} from '../types/aliases.js';
import type {SoloListrTask} from '../types/index.js';

export class DeploymentCommand extends BaseCommand {
private static get DEPLOY_FLAGS_LIST(): CommandFlag[] {
return [
flags.quiet,
flags.namespace,
flags.userEmailAddress,
flags.deploymentClusters,
flags.contextClusterUnparsed,
];
return [flags.quiet, flags.namespace, flags.userEmailAddress, flags.deploymentClusters];
}

private async create(argv: any): Promise<boolean> {
Expand All @@ -45,8 +38,6 @@ export class DeploymentCommand extends BaseCommand {

interface Config {
namespace: Namespace;
contextClusterUnparsed: string;
contextCluster: ContextClusterStructure;
}
interface Context {
config: Config;
Expand All @@ -56,22 +47,16 @@ export class DeploymentCommand extends BaseCommand {
[
{
title: 'Initialize',
task: async (ctx, task): Promise<Listr<Context, any, any>> => {
task: async (ctx, task) => {
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});

return ListrLease.newAcquireLeaseTask(lease, task);
Expand All @@ -81,16 +66,19 @@ export class DeploymentCommand extends BaseCommand {
this.localConfig.promptLocalConfigTask(self.k8),
{
title: 'Validate cluster connections',
task: async (ctx, task): Promise<Listr<Context, any, any>> => {
const subTasks = [];
task: async (ctx, task) => {
const subTasks: SoloListrTask<Context>[] = [];

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

for (const context of Object.keys(ctx.config.contextCluster)) {
const cluster = ctx.config.contextCluster[context];
subTasks.push({
title: `Testing connection to cluster: ${chalk.cyan(cluster)}`,
task: async (_: Context, task: ListrTaskWrapper<Context, any, any>) => {
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 All @@ -106,9 +94,12 @@ export class DeploymentCommand extends BaseCommand {
{
title: 'Create remoteConfig in clusters',
task: async (ctx, task) => {
const subTasks = [];
for (const context of Object.keys(ctx.config.contextCluster)) {
const cluster = ctx.config.contextCluster[context];
const subTasks: SoloListrTask<Context>[] = [];

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

subTasks.push(RemoteConfigTasks.createRemoteConfig.bind(this)(cluster, context, ctx.config.namespace));
}

Expand All @@ -127,7 +118,7 @@ export class DeploymentCommand extends BaseCommand {

try {
await tasks.run();
} catch (e: Error | any) {
} catch (e: Error | unknown) {
throw new SoloError(`Error installing chart ${constants.SOLO_DEPLOYMENT_CHART}`, e);
} finally {
await lease.release();
Expand Down
22 changes: 0 additions & 22 deletions src/commands/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1595,27 +1595,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 @@ -1744,7 +1723,6 @@ export class Flags {
Flags.clusterName,
Flags.clusterSetupNamespace,
Flags.context,
Flags.contextClusterUnparsed,
Flags.createAmount,
Flags.debugNodeAlias,
Flags.deletePvcs,
Expand Down
3 changes: 1 addition & 2 deletions src/core/config/remote/remote_config_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ 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 * as k8s from '@kubernetes/client-node';
import {StatusCodes} from 'http-status-codes';
Expand All @@ -38,7 +37,7 @@ import {patchInject} from '../../container_helper.js';
import {ErrorMessages} from '../../error_messages.js';

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

/**
Expand Down
21 changes: 16 additions & 5 deletions src/core/k8.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1206,11 +1206,22 @@
public async testClusterConnection(context: string, cluster: string): Promise<boolean> {
this.kubeConfig.setCurrentContext(context);

const tempKubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
return await tempKubeClient
.listNamespace()
.then(() => this.getKubeConfig().getCurrentCluster().name === cluster)
.catch(() => false);
const clusters = this.kubeConfig.getClusters();
const matchingCluster = clusters.find(c => c.name === cluster);

if (!matchingCluster) {
this.logger.error(`Cluster "${cluster}" not found in kubeconfig.`);
return false;
}

try {
await this.kubeConfig.makeApiClient(k8s.CoreV1Api).listNamespace();

return true;
} catch (error) {
this.logger.error('Error verifying cluster connectivity', error);
return false;
}

Check warning on line 1224 in src/core/k8.ts

View check run for this annotation

Codecov / codecov/patch

src/core/k8.ts#L1209-L1224

Added lines #L1209 - L1224 were not covered by tests
}

// --------------------------------------- Secret --------------------------------------- //
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
2 changes: 0 additions & 2 deletions src/types/config_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,3 @@
*
*/
import type {Cluster, Context} from '../core/config/remote/types.js';

export type ContextClusterStructure = Record<Context, Cluster>;
Loading