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

fix: update RemoteConfig to handle multi-cluster networking #1348

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions src/commands/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as constants from '../core/constants.js';
import chalk from 'chalk';
import {ListrRemoteConfig} from '../core/config/remote/listr_config_tasks.js';
import {ClusterCommandTasks} from './cluster/tasks.js';
import {type DeploymentName, type NamespaceNameAsString, type Cluster} from '../core/config/remote/types.js';
import {type DeploymentName, type NamespaceNameAsString, type ClusterRef} from '../core/config/remote/types.js';
import {type CommandFlag} from '../types/flag_types.js';
import {type CommandBuilder} from '../types/aliases.js';
import {type SoloListrTask} from '../types/index.js';
Expand Down Expand Up @@ -168,7 +168,7 @@ export class DeploymentCommand extends BaseCommand {
const self = this;

interface Config {
clusterName: Cluster;
clusterName: ClusterRef;
}

interface Context {
Expand All @@ -186,7 +186,7 @@ export class DeploymentCommand extends BaseCommand {
await self.configManager.executePrompt(task, [flags.clusterName]);

ctx.config = {
clusterName: self.configManager.getFlag<Cluster>(flags.clusterName),
clusterName: self.configManager.getFlag<ClusterRef>(flags.clusterName),
} as Config;

self.logger.debug('Prepared config', {config: ctx.config, cachedConfig: self.configManager.config});
Expand Down
8 changes: 7 additions & 1 deletion src/commands/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,13 @@
for (const nodeAlias of nodeAliases) {
remoteConfig.components.add(
nodeAlias,
new ConsensusNodeComponent(nodeAlias, cluster, namespace.name, ConsensusNodeStates.INITIALIZED),
new ConsensusNodeComponent(
nodeAlias,
cluster,
namespace.name,
ConsensusNodeStates.INITIALIZED,
Templates.nodeIdFromNodeAlias(nodeAlias),
),

Check warning on line 973 in src/commands/network.ts

View check run for this annotation

Codecov / codecov/patch

src/commands/network.ts#L967-L973

Added lines #L967 - L973 were not covered by tests
);

remoteConfig.components.add(
Expand Down
10 changes: 8 additions & 2 deletions src/commands/node/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
import chalk from 'chalk';
import {type ComponentsDataWrapper} from '../../core/config/remote/components_data_wrapper.js';
import {type Optional} from '../../types/index.js';
import {type NamespaceNameAsString} from '../../core/config/remote/types.js';
import {type NamespaceName} from '../../core/kube/resources/namespace/namespace_name.js';
import {Templates} from '../../core/templates.js';

export class NodeCommandHandlers implements CommandHandlers {
private readonly accountManager: AccountManager;
Expand Down Expand Up @@ -879,7 +879,13 @@
for (const nodeAlias of nodeAliases) {
remoteConfig.components.edit(
nodeAlias,
new ConsensusNodeComponent(nodeAlias, cluster, namespace.name, state),
new ConsensusNodeComponent(
nodeAlias,
cluster,
namespace.name,
state,
Templates.nodeIdFromNodeAlias(nodeAlias),
),

Check warning on line 888 in src/commands/node/handlers.ts

View check run for this annotation

Codecov / codecov/patch

src/commands/node/handlers.ts#L882-L888

Added lines #L882 - L888 were not covered by tests
);
}
});
Expand Down
6 changes: 3 additions & 3 deletions src/core/config/local_config_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import {
type Cluster,
type ClusterRef,
type Context,
type EmailAddress,
type NamespaceNameAsString,
Expand All @@ -11,11 +11,11 @@ import {

export interface DeploymentStructure {
// A list of clusters on which the deployment is deployed
clusters: Cluster[];
clusters: ClusterRef[];
namespace: NamespaceNameAsString;
}

export type ClusterContextMapping = Record<Cluster, Context>;
export type ClusterContextMapping = Record<ClusterRef, Context>;

export type Deployments = Record<DeploymentName, DeploymentStructure>;

Expand Down
91 changes: 91 additions & 0 deletions src/core/config/remote/cluster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* SPDX-License-Identifier: Apache-2.0
*/
import {type ToObject} from '../../../types/index.js';
import {type ClusterRef, type ICluster, type NamespaceNameAsString} from './types.js';
import {SoloError} from '../../errors.js';

export class Cluster implements ICluster, ToObject<ICluster> {
private readonly _name: string;
private readonly _namespace: string;
private readonly _dnsBaseDomain: string = 'cluster.local'; // example: 'us-west-2.gcp.charlie.sphere'`
private readonly _dnsConsensusNodePattern: string = 'network-${nodeAlias}-svc.${namespace}.svc'; // example: '${nodeId}.consensus.prod'`

public constructor(
name: string,
namespace: NamespaceNameAsString,
dnsBaseDomain?: string,
dnsConsensusNodePattern?: string,
) {
if (!name) {
throw new SoloError('name is required');
}

if (typeof name !== 'string') {
throw new SoloError(`Invalid type for name: ${typeof name}`);
}

if (!namespace) {
throw new SoloError('namespace is required');
}

if (typeof namespace !== 'string') {
throw new SoloError(`Invalid type for namespace: ${typeof namespace}`);
}

this._name = name;
this._namespace = namespace;

if (dnsBaseDomain) {
this._dnsBaseDomain = dnsBaseDomain;
}

if (dnsConsensusNodePattern) {
this._dnsConsensusNodePattern = dnsConsensusNodePattern;
}
}

public get name(): string {
return this._name;
}

public get namespace(): string {
return this._namespace;
}

public get dnsBaseDomain(): string {
return this._dnsBaseDomain;
}

public get dnsConsensusNodePattern(): string {
return this._dnsConsensusNodePattern;
}

public toObject(): ICluster {
return {
name: this.name,
namespace: this.namespace,
dnsBaseDomain: this.dnsBaseDomain,
dnsConsensusNodePattern: this.dnsConsensusNodePattern,
};
}

public static fromObject(cluster: ICluster) {
return new Cluster(cluster.name, cluster.namespace, cluster.dnsBaseDomain, cluster.dnsConsensusNodePattern);
}

public static toClustersMapObject(clustersMap: Record<ClusterRef, Cluster>) {
const entries = Object.entries(clustersMap).map(([ref, cluster]) => [ref, cluster.toObject()]);
return Object.fromEntries(entries);
}

public static fromClustersMapObject(obj: any): Record<ClusterRef, Cluster> {
const clusters: Record<ClusterRef, Cluster> = {};

for (const [ref, cluster] of Object.entries(obj)) {
clusters[ref] = Cluster.fromObject(cluster as ICluster);
}

return clusters;
}
}
4 changes: 2 additions & 2 deletions src/core/config/remote/components/base_component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import {ComponentType} from '../enumerations.js';
import {SoloError} from '../../../errors.js';
import {type Cluster, type Component, type ComponentName, type NamespaceNameAsString} from '../types.js';
import {type ClusterRef, type Component, type ComponentName, type NamespaceNameAsString} from '../types.js';
import {type ToObject, type Validate} from '../../../../types/index.js';

/**
Expand All @@ -20,7 +20,7 @@ export abstract class BaseComponent implements Component, Validate, ToObject<Com
protected constructor(
public readonly type: ComponentType,
public readonly name: ComponentName,
public readonly cluster: Cluster,
public readonly cluster: ClusterRef,
public readonly namespace: NamespaceNameAsString,
) {}

Expand Down
24 changes: 20 additions & 4 deletions src/core/config/remote/components/consensus_node_component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
import {ComponentType, ConsensusNodeStates} from '../enumerations.js';
import {BaseComponent} from './base_component.js';
import {SoloError} from '../../../errors.js';
import {type Cluster, type IConsensusNodeComponent, type ComponentName, type NamespaceNameAsString} from '../types.js';
import {
type ClusterRef,
type ComponentName,
type IConsensusNodeComponent,
type NamespaceNameAsString,
} from '../types.js';
import {type ToObject} from '../../../../types/index.js';

/**
Expand All @@ -19,15 +24,17 @@ export class ConsensusNodeComponent
{
/**
* @param name - the name to distinguish components.
* @param nodeId - node id of the consensus node
* @param cluster - associated to component
* @param namespace - associated to component
* @param state - of the consensus node
*/
public constructor(
name: ComponentName,
cluster: Cluster,
cluster: ClusterRef,
namespace: NamespaceNameAsString,
public readonly state: ConsensusNodeStates,
public readonly nodeId: number,
) {
super(ComponentType.ConsensusNode, name, cluster, namespace);

Expand All @@ -38,8 +45,8 @@ export class ConsensusNodeComponent

/** Handles creating instance of the class from plain object. */
public static fromObject(component: IConsensusNodeComponent): ConsensusNodeComponent {
const {name, cluster, namespace, state} = component;
return new ConsensusNodeComponent(name, cluster, namespace, state);
const {name, cluster, namespace, state, nodeId} = component;
return new ConsensusNodeComponent(name, cluster, namespace, state, nodeId);
}

public validate(): void {
Expand All @@ -48,12 +55,21 @@ export class ConsensusNodeComponent
if (!Object.values(ConsensusNodeStates).includes(this.state)) {
throw new SoloError(`Invalid consensus node state: ${this.state}`);
}

if (typeof this.nodeId !== 'number') {
throw new SoloError(`Invalid node id. It must be a number: ${this.nodeId}`);
}

if (this.nodeId < 0) {
throw new SoloError(`Invalid node id. It cannot be negative: ${this.nodeId}`);
}
}

public toObject(): IConsensusNodeComponent {
return {
...super.toObject(),
state: this.state,
nodeId: this.nodeId,
};
}
}
2 changes: 1 addition & 1 deletion src/core/config/remote/enumerations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export enum ComponentType {
EnvoyProxy = 'envoyProxies',
MirrorNode = 'mirrorNodes',
MirrorNodeExplorer = 'mirrorNodeExplorers',
Relay = 'replays',
Relay = 'relays',
}

/**
Expand Down
14 changes: 7 additions & 7 deletions src/core/config/remote/listr_config_tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import chalk from 'chalk';
import {type BaseCommand} from '../../../commands/base.js';
import {type Cluster, type Context} from './types.js';
import {type ClusterRef, type Context} from './types.js';
import {type SoloListrTask} from '../../../types/index.js';
import {type AnyObject} from '../../../types/aliases.js';
import {type NamespaceName} from '../../kube/resources/namespace/namespace_name.js';
Expand Down Expand Up @@ -41,15 +41,15 @@
*/
public static createRemoteConfig(
command: BaseCommand,
cluster: Cluster,
clusterRef: ClusterRef,

Check warning on line 44 in src/core/config/remote/listr_config_tasks.ts

View check run for this annotation

Codecov / codecov/patch

src/core/config/remote/listr_config_tasks.ts#L44

Added line #L44 was not covered by tests
context: Context,
namespace: NamespaceName,
argv: AnyObject,
): SoloListrTask<any> {
return {
title: `Create remote config in cluster: ${chalk.cyan(cluster)}`,
title: `Create remote config in cluster: ${chalk.cyan(clusterRef)}`,

Check warning on line 50 in src/core/config/remote/listr_config_tasks.ts

View check run for this annotation

Codecov / codecov/patch

src/core/config/remote/listr_config_tasks.ts#L50

Added line #L50 was not covered by tests
task: async (): Promise<void> => {
await command.getRemoteConfigManager().createAndValidate(cluster, context, namespace.name, argv);
await command.getRemoteConfigManager().createAndValidate(clusterRef, context, namespace.name, argv);

Check warning on line 52 in src/core/config/remote/listr_config_tasks.ts

View check run for this annotation

Codecov / codecov/patch

src/core/config/remote/listr_config_tasks.ts#L52

Added line #L52 was not covered by tests
},
};
}
Expand All @@ -66,11 +66,11 @@
task: async (ctx, task) => {
const subTasks: SoloListrTask<Context>[] = [];

for (const cluster of command.localConfig.deployments[ctx.config.deployment].clusters) {
const context = command.localConfig.clusterContextMapping?.[cluster];
for (const clusterRef of command.localConfig.deployments[ctx.config.deployment].clusters) {
const context = command.localConfig.clusterContextMapping?.[clusterRef];

Check warning on line 70 in src/core/config/remote/listr_config_tasks.ts

View check run for this annotation

Codecov / codecov/patch

src/core/config/remote/listr_config_tasks.ts#L69-L70

Added lines #L69 - L70 were not covered by tests
if (!context) continue;

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

Check warning on line 73 in src/core/config/remote/listr_config_tasks.ts

View check run for this annotation

Codecov / codecov/patch

src/core/config/remote/listr_config_tasks.ts#L73

Added line #L73 was not covered by tests
}

return task.newListr(subTasks, {
Expand Down
5 changes: 3 additions & 2 deletions src/core/config/remote/remote_config_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import {type RemoteConfigMetadata} from './metadata.js';
import {type ComponentsDataWrapper} from './components_data_wrapper.js';
import {type CommonFlagsDataWrapper} from './common_flags_data_wrapper.js';
import {type Cluster, type NamespaceNameAsString} from './types.js';
import {type ClusterRef} from './types.js';
import {type Cluster} from './cluster.js';

export interface RemoteConfigData {
metadata: RemoteConfigMetadata;
clusters: Record<Cluster, NamespaceNameAsString>;
clusters: Record<ClusterRef, Cluster>;
components: ComponentsDataWrapper;
lastExecutedCommand: string;
commandHistory: string[];
Expand Down
Loading
Loading