diff --git a/src/commands/network.ts b/src/commands/network.ts index 50c8a81a5..9fbac6b26 100644 --- a/src/commands/network.ts +++ b/src/commands/network.ts @@ -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, + }, + ); }, }, { diff --git a/src/commands/node/tasks.ts b/src/commands/node/tasks.ts index 8090ae61d..ceb00d6a8 100644 --- a/src/commands/node/tasks.ts +++ b/src/commands/node/tasks.ts @@ -1486,7 +1486,11 @@ export class NodeCommandTasks { copyNodeKeysToSecrets() { return new Task('Copy node keys to secrets', (ctx: any, task: ListrTaskWrapper) => { - 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, { diff --git a/src/core/platform_installer.ts b/src/core/platform_installer.ts index 6da619ce8..d625b54d2 100644 --- a/src/core/platform_installer.ts +++ b/src/core/platform_installer.ts @@ -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() @@ -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 = {}; @@ -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); @@ -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); @@ -324,25 +329,26 @@ export class PlatformInstaller { *
  • ${staging}/keys/hedera-.crt: gRPC TLS cert for a node
  • * * @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), }, ], {