Skip to content

Commit

Permalink
removed final todo for network deploy
Browse files Browse the repository at this point in the history
Signed-off-by: Jeromy Cannon <[email protected]>
  • Loading branch information
jeromy-cannon committed Feb 12, 2025
1 parent 03ad78f commit b9f6d10
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 45 deletions.
11 changes: 7 additions & 4 deletions src/commands/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -697,10 +697,13 @@ export class NetworkCommand extends BaseCommand {
const config = ctx.config;

// set up the subtasks
return parentTask.newListr(self.platformInstaller.copyNodeKeys(config.stagingDir, config.nodeAliases), {
concurrent: true,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
});
return parentTask.newListr(
self.platformInstaller.copyNodeKeys(config.stagingDir, config.consensusNodes, config.contexts),
{
concurrent: true,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
},
);
},
},
{
Expand Down
6 changes: 5 additions & 1 deletion src/commands/node/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,11 @@ export class NodeCommandTasks {

copyNodeKeysToSecrets() {
return new Task('Copy node keys to secrets', (ctx: any, task: ListrTaskWrapper<any, any, any>) => {
const subTasks = this.platformInstaller.copyNodeKeys(ctx.config.stagingDir, ctx.config.allNodeAliases);
const subTasks = this.platformInstaller.copyNodeKeys(
ctx.config.stagingDir,
ctx.config.allNodeAliases,
ctx.config.contexts,
);

// set up the sub-tasks for copying node keys to staging directory
return task.newListr(subTasks, {
Expand Down
86 changes: 46 additions & 40 deletions src/core/platform_installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ import * as Base64 from 'js-base64';
import chalk from 'chalk';

import {type SoloLogger} from './logging.js';
import {type NodeAlias, type NodeAliases} from '../types/aliases.js';
import {type NodeAlias} from '../types/aliases.js';
import {Duration} from './time/duration.js';
import {sleep} from './helpers.js';
import {inject, injectable} from 'tsyringe-neo';
import {patchInject} from './dependency_injection/container_helper.js';
import {type NamespaceName} from './kube/resources/namespace/namespace_name.js';
import {NamespaceName} from './kube/resources/namespace/namespace_name.js';
import {type PodRef} from './kube/resources/pod/pod_ref.js';
import {ContainerRef} from './kube/resources/container/container_ref.js';
import {SecretType} from './kube/resources/secret/secret_type.js';
import {InjectTokens} from './dependency_injection/inject_tokens.js';
import {type ConsensusNode} from './model/consensus_node.js';

/** PlatformInstaller install platform code in the root-container of a network pod */
@injectable()
Expand Down Expand Up @@ -144,20 +145,24 @@ export class PlatformInstaller {
}
}

async copyGossipKeys(nodeAlias: NodeAlias, stagingDir: string, nodeAliases: NodeAliases) {
if (!nodeAlias) throw new MissingArgumentError('nodeAlias is required');
async copyGossipKeys(consensusNode: ConsensusNode, stagingDir: string, consensusNodes: ConsensusNode[]) {
if (!consensusNode) throw new MissingArgumentError('consensusNode is required');
if (!stagingDir) throw new MissingArgumentError('stagingDir is required');
if (!nodeAliases || nodeAliases.length <= 0) throw new MissingArgumentError('nodeAliases cannot be empty');
if (!consensusNodes || consensusNodes.length <= 0) throw new MissingArgumentError('consensusNodes cannot be empty');

try {
const srcFiles = [];

// copy private keys for the node
srcFiles.push(path.join(stagingDir, 'keys', Templates.renderGossipPemPrivateKeyFile(nodeAlias)));
srcFiles.push(
path.join(stagingDir, 'keys', Templates.renderGossipPemPrivateKeyFile(consensusNode.name as NodeAlias)),
);

// copy all public keys for all nodes
nodeAliases.forEach(nodeAlias => {
srcFiles.push(path.join(stagingDir, 'keys', Templates.renderGossipPemPublicKeyFile(nodeAlias)));
consensusNodes.forEach(consensusNode => {
srcFiles.push(
path.join(stagingDir, 'keys', Templates.renderGossipPemPublicKeyFile(consensusNode.name as NodeAlias)),
);
});

const data = {};
Expand All @@ -168,44 +173,42 @@ export class PlatformInstaller {
data[fileName] = Base64.encode(fileContents);
}

// TODO: @Lenin, will need to run for each cluster
const secretCreated = await this.k8Factory
.default()
.getK8(consensusNode.context)
.secrets()
.createOrReplace(
this._getNamespace(),
Templates.renderGossipKeySecretName(nodeAlias),
NamespaceName.of(consensusNode.namespace),
Templates.renderGossipKeySecretName(consensusNode.name as NodeAlias),
SecretType.OPAQUE,
data,
Templates.renderGossipKeySecretLabelObject(nodeAlias),
Templates.renderGossipKeySecretLabelObject(consensusNode.name as NodeAlias),
);

if (!secretCreated) {
throw new SoloError(`failed to create secret for gossip keys for node '${nodeAlias}'`);
throw new SoloError(`failed to create secret for gossip keys for node '${consensusNode.name}'`);
}
} catch (e: Error | any) {
this.logger.error(
`failed to copy gossip keys to secret '${Templates.renderGossipKeySecretName(nodeAlias)}': ${e.message}`,
e,
);
throw new SoloError(
`failed to copy gossip keys to secret '${Templates.renderGossipKeySecretName(nodeAlias)}': ${e.message}`,
e,
);
const message = `failed to copy gossip keys to secret '${Templates.renderGossipKeySecretName(consensusNode.name as NodeAlias)}': ${e.message}`;
this.logger.error(message, e);
throw new SoloError(message, e);
}
}

async copyTLSKeys(nodeAliases: NodeAliases, stagingDir: string) {
if (!nodeAliases || nodeAliases.length <= 0) throw new MissingArgumentError('nodeAliases cannot be empty');
async copyTLSKeys(consensusNodes: ConsensusNode[], stagingDir: string, contexts: string[]) {
if (!consensusNodes || consensusNodes.length <= 0) throw new MissingArgumentError('consensusNodes cannot be empty');
if (!stagingDir) throw new MissingArgumentError('stagingDir is required');

try {
const data = {};

for (const nodeAlias of nodeAliases) {
for (const consensusNode of consensusNodes) {
const srcFiles = [];
srcFiles.push(path.join(stagingDir, 'keys', Templates.renderTLSPemPrivateKeyFile(nodeAlias)));
srcFiles.push(path.join(stagingDir, 'keys', Templates.renderTLSPemPublicKeyFile(nodeAlias)));
srcFiles.push(
path.join(stagingDir, 'keys', Templates.renderTLSPemPrivateKeyFile(consensusNode.name as NodeAlias)),
);
srcFiles.push(
path.join(stagingDir, 'keys', Templates.renderTLSPemPublicKeyFile(consensusNode.name as NodeAlias)),
);

for (const srcFile of srcFiles) {
const fileContents = fs.readFileSync(srcFile);
Expand All @@ -214,14 +217,16 @@ export class PlatformInstaller {
data[fileName] = Base64.encode(fileContents);
}
}
// TODO: @Lenin, will need to run for each cluster
const secretCreated = await this.k8Factory
.default()
.secrets()
.createOrReplace(this._getNamespace(), 'network-node-hapi-app-secrets', SecretType.OPAQUE, data, undefined);

if (!secretCreated) {
throw new SoloError('failed to create secret for TLS keys');
for (const context of contexts) {
const secretCreated = await this.k8Factory
.getK8(context)
.secrets()
.createOrReplace(this._getNamespace(), 'network-node-hapi-app-secrets', SecretType.OPAQUE, data, undefined);

if (!secretCreated) {
throw new SoloError('failed to create secret for TLS keys');
}
}
} catch (e: Error | any) {
this.logger.error('failed to copy TLS keys to secret', e);
Expand Down Expand Up @@ -324,25 +329,26 @@ export class PlatformInstaller {
* <li>${staging}/keys/hedera-<nodeAlias>.crt: gRPC TLS cert for a node</li>
*
* @param stagingDir staging directory path
* @param nodeAliases list of node ids
* @param consensusNodes list of consensus nodes
* @param contexts list of k8s contexts
*/
copyNodeKeys(stagingDir: string, nodeAliases: NodeAliases) {
copyNodeKeys(stagingDir: string, consensusNodes: ConsensusNode[], contexts: string[]) {
const self = this;
const subTasks = [];
subTasks.push({
title: 'Copy TLS keys',
task: async () => await self.copyTLSKeys(nodeAliases, stagingDir),
task: async () => await self.copyTLSKeys(consensusNodes, stagingDir, contexts),
});

for (const nodeAlias of nodeAliases) {
for (const consensusNode of consensusNodes) {
subTasks.push({
title: `Node: ${chalk.yellow(nodeAlias)}`,
title: `Node: ${chalk.yellow(consensusNode.name)}, cluster: ${chalk.yellow(consensusNode.context)}`,
task: () =>
new Listr(
[
{
title: 'Copy Gossip keys',
task: async () => await self.copyGossipKeys(nodeAlias, stagingDir, nodeAliases),
task: async () => await self.copyGossipKeys(consensusNode, stagingDir, consensusNodes),
},
],
{
Expand Down

0 comments on commit b9f6d10

Please sign in to comment.