diff --git a/src/eth/command/backup.ts b/src/eth/command/backup.ts index 880c52d..0f2c553 100644 --- a/src/eth/command/backup.ts +++ b/src/eth/command/backup.ts @@ -2,7 +2,7 @@ import { Argv } from 'yargs' export const command = 'backup' -export const desc = '管理 Eth backup 的指令' +export const desc = '管理 Eth Network backup 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('backup').demandCommand() diff --git a/src/eth/command/cluster.ts b/src/eth/command/cluster.ts index 5cda8ba..525f22b 100644 --- a/src/eth/command/cluster.ts +++ b/src/eth/command/cluster.ts @@ -2,7 +2,7 @@ import { Argv } from 'yargs' export const command = 'cluster' -export const desc = '管理 Eth cluster 的指令' +export const desc = '管理 Eth Network cluster 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('cluster').demandCommand() diff --git a/src/eth/command/cluster/apply.ts b/src/eth/command/cluster/apply.ts index 19b4525..bc477f4 100644 --- a/src/eth/command/cluster/apply.ts +++ b/src/eth/command/cluster/apply.ts @@ -12,7 +12,7 @@ import ora from 'ora' import { getNetworkTypeChoices, NetworkType } from '../../config/network.type' export const command = 'apply' -export const desc = '產生 Network Cluster 所需的相關設定檔案並建立網路' +export const desc = '產生 Eth Network Cluster 所需的相關設定檔案並建立網路' interface OptType { interactive: boolean @@ -20,7 +20,7 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum cluster apply --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network cluster apply --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } export const handler = async (argv: Arguments) => { @@ -33,6 +33,7 @@ export const handler = async (argv: Arguments) => { }, ]) as { networkType: NetworkType } + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) const cluster = new Cluster(config, networkType) const wallet = new Wallet() @@ -42,11 +43,11 @@ export const handler = async (argv: Arguments) => { const confirmDelete = (await prompts({ type: 'confirm', name: 'value', - message: '⚠️ Detecting cluster already exists. The following processes will remove all existing files. Continue?', + message: `⚠️ Detecting ${networkTypeWithBigFirstLetter} cluster already exists. The following processes will remove all existing files. Continue?`, initial: false, }, { onCancel })).value if (confirmDelete) { - const spinner = ora(`${networkType} Cluster Delete ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Cluster Delete ...`).start() cluster.removeHelmChartFiles() spinner.succeed('Remove all existing files!') } @@ -168,12 +169,12 @@ export const handler = async (argv: Arguments) => { return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList, networkType } } else { const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM) - const config = defaultNetworkConfig(address, privateKey) + const config = defaultNetworkConfig(address, privateKey, networkType) return { ...config, provider: 'local', networkType } } })() - const spinner = ora(`${networkType} Cluster Apply ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Cluster Apply ...`).start() await cluster.apply(clusterCreate, spinner) - spinner.succeed(`${networkType} Cluster Apply Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Cluster Apply Successfully!`) } } diff --git a/src/eth/command/cluster/delete.ts b/src/eth/command/cluster/delete.ts index b61d658..04643bc 100644 --- a/src/eth/command/cluster/delete.ts +++ b/src/eth/command/cluster/delete.ts @@ -4,10 +4,11 @@ import Cluster from '../../service/cluster' import { onCancel } from '../../../util/error' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices, NetworkType } from '../../config/network.type' export const command = 'delete' -export const desc = '刪除現有的 Quorum Cluster 網路' +export const desc = '刪除現有的 Eth Network Cluster 網路' interface OptType { interactive: boolean @@ -15,26 +16,28 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum cluster delete', 'Cathay BDK 互動式問答') + .example('bdk eth network cluster delete', 'Cathay BDK 互動式問答') } export const handler = async () => { - const cluster = new Cluster(config, 'quorum') + const { networkType } = await prompts([{ + type: 'select', + name: 'networkType', + message: 'What is your network?', + choices: getNetworkTypeChoices(), + }]) as { networkType: NetworkType } + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) + const cluster = new Cluster(config, networkType) const confirm: boolean = await (async () => { const fileList = cluster.getHelmChartFiles() if (fileList.length !== 0) { const confirmDelete = (await prompts({ type: 'confirm', name: 'value', - message: '⚠️ Detecting quorum cluster already exists. The following processes will remove all existing files. Continue?', + message: `⚠️ Detecting ${networkTypeWithBigFirstLetter} cluster already exists. The following processes will remove all existing files. Continue?`, initial: false, }, { onCancel })).value - if (confirmDelete) { - const spinner = ora('Quorum Cluster Create ...').start() - cluster.removeHelmChartFiles() - spinner.succeed('Remove all existing files!') - } return confirmDelete } else { return true @@ -42,8 +45,9 @@ export const handler = async () => { })() if (confirm) { - const spinner = ora('Deployments Under Namespace Quorum Delete ...').start() - await cluster.delete() - spinner.succeed('Quorum Cluster Delete Successfully!') + const spinner = ora(`${networkTypeWithBigFirstLetter} Cluster Delete ...`).start() + await cluster.delete(networkType) + cluster.removeHelmChartFiles() + spinner.succeed(`${networkTypeWithBigFirstLetter} Cluster Delete Successfully!`) } } diff --git a/src/eth/command/cluster/generate.ts b/src/eth/command/cluster/generate.ts index 37fe040..e68fa94 100644 --- a/src/eth/command/cluster/generate.ts +++ b/src/eth/command/cluster/generate.ts @@ -13,7 +13,7 @@ import { getNetworkTypeChoices, NetworkType } from '../../config/network.type' export const command = 'generate' -export const desc = '產生 Network Cluster 所需的相關設定檔案' +export const desc = '產生 Eth Network Cluster 所需的相關設定檔案' interface OptType { interactive: boolean @@ -21,7 +21,7 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk network cluster generate --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network cluster generate --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } @@ -34,6 +34,8 @@ export const handler = async (argv: Arguments) => { choices: getNetworkTypeChoices(), }, ]) as { networkType: NetworkType } + + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) const cluster = new Cluster(config, networkType) const wallet = new Wallet() @@ -43,11 +45,11 @@ export const handler = async (argv: Arguments) => { const confirmDelete = (await prompts({ type: 'confirm', name: 'value', - message: '⚠️ Detecting cluster already exists. The following processes will remove all existing files. Continue?', + message: `⚠️ Detecting ${networkTypeWithBigFirstLetter} cluster already exists. The following processes will remove all existing files. Continue?`, initial: false, }, { onCancel })).value if (confirmDelete) { - const spinner = ora(`${networkType} Cluster Delete ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Cluster Delete ...`).start() cluster.removeHelmChartFiles() spinner.succeed('Remove all existing files!') } @@ -195,13 +197,13 @@ export const handler = async (argv: Arguments) => { return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList, networkType } } else { const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM) - const config = defaultNetworkConfig(address, privateKey) + const config = defaultNetworkConfig(address, privateKey, networkType) return { ...config, provider: 'local', networkType } } })() - const spinner = ora(`${networkType} Cluster Generate ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Cluster Generate ...`).start() await cluster.generate(clusterGenerate, networkCreate) - spinner.succeed(`${networkType} Cluster Generate Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Cluster Generate Successfully!`) } } diff --git a/src/eth/command/explorer.ts b/src/eth/command/explorer.ts index 70c00bb..355f9e3 100644 --- a/src/eth/command/explorer.ts +++ b/src/eth/command/explorer.ts @@ -2,7 +2,7 @@ import { Argv } from 'yargs' export const command = 'explorer' -export const desc = '管理 Eth explorer 的指令' +export const desc = '管理 Eth Network explorer 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('explorer').demandCommand() diff --git a/src/eth/command/explorer/create.ts b/src/eth/command/explorer/create.ts index 569926f..c82048b 100644 --- a/src/eth/command/explorer/create.ts +++ b/src/eth/command/explorer/create.ts @@ -6,6 +6,7 @@ import prompts from 'prompts' import ora from 'ora' import { ExplorerCreateType } from '../../model/type/explorer.type' import Backup from '../../service/backup' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'create' @@ -22,9 +23,15 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const explorer = new Explorer(config, 'quorum') - const backup = new Backup(config, 'quorum') - + const { networkType } = await prompts([{ + type: 'select', + name: 'networkType', + message: 'What is yours network?', + choices: getNetworkTypeChoices(), + }]) + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) + const explorer = new Explorer(config, networkType) + const backup = new Backup(config, networkType) const getBackupItems = backup.getExportItems() const explorerCreate: ExplorerCreateType = await (async () => { if (argv.interactive) { @@ -70,7 +77,7 @@ export const handler = async (argv: Arguments) => { } })() - const spinner = ora('Quorum Explorer Create ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Explorer Create ...`).start() await explorer.create(explorerCreate) - spinner.succeed(`Quorum Explorer Create Successfully! Host at: http://localhost:${explorerCreate.port}`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Explorer Create Successfully! Host at: http://localhost:${explorerCreate.port}`) } diff --git a/src/eth/command/explorer/delete.ts b/src/eth/command/explorer/delete.ts index 82baa2e..d102fe9 100644 --- a/src/eth/command/explorer/delete.ts +++ b/src/eth/command/explorer/delete.ts @@ -3,30 +3,40 @@ import Explorer from '../../service/explorer' import { onCancel } from '../../../util' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'delete' -export const desc = '刪除現有的 Quorum Explorer.' +export const desc = '刪除現有的 Eth Network Explorer.' export const builder = {} export const handler = async () => { - const explorer = new Explorer(config, 'quorum') + const { networkType } = await prompts([ + { + type: 'select', + name: 'networkType', + message: 'What is your network?', + choices: getNetworkTypeChoices(), + }, + ]) + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) + const explorer = new Explorer(config, networkType) let confirmDelete = true const response = await prompts({ type: 'confirm', name: 'value', - message: '⚠️ The following processes will remove all explorer files. Confirm to delete Quorum Explorer?', + message: `⚠️ The following processes will remove all explorer files. Confirm to delete ${networkTypeWithBigFirstLetter} Explorer?`, initial: false, }, { onCancel }) confirmDelete = response.value if (confirmDelete) { - const spinner = ora('Quorum Explorer Delete ...').start() + const spinner = ora(`${networkType} Explorer Delete ...`).start() await explorer.delete() - spinner.succeed('Quorum Explorer Delete Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Explorer Delete Successfully!`) } } diff --git a/src/eth/command/network.ts b/src/eth/command/network.ts index ebff574..64a33da 100644 --- a/src/eth/command/network.ts +++ b/src/eth/command/network.ts @@ -2,7 +2,7 @@ import { Argv } from 'yargs' export const command = 'network' -export const desc = '管理 Eth network 的指令' +export const desc = '管理 Eth Network network 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('network').demandCommand() diff --git a/src/eth/command/network/add.ts b/src/eth/command/network/add.ts index ebe506d..82b324a 100644 --- a/src/eth/command/network/add.ts +++ b/src/eth/command/network/add.ts @@ -10,7 +10,7 @@ import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'add' -export const desc = '新增 Quorum Node' +export const desc = '新增 Eth Network Node' interface OptType { interactive: boolean @@ -18,7 +18,7 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network add --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network add --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } @@ -64,11 +64,11 @@ export const handler = async (argv: Arguments) => { if (connectOption === 'local') { if (nodeOption === 'validator') { const spinner = ora(`${networkTypeWithBigFirstLetter} Network Add ...`).start() - const validatorNum = await network.addValidatorLocal() + const validatorNum = await network.addValidatorLocal(networkType) spinner.succeed(`${networkTypeWithBigFirstLetter} Network Add Validator${validatorNum} Successfully!`) } else { const spinner = ora(`${networkTypeWithBigFirstLetter} Network Add ...`).start() - const memberNum = await network.addMemberLocal() + const memberNum = await network.addMemberLocal(networkType) spinner.succeed(`${networkTypeWithBigFirstLetter} Network Add Member${memberNum} Successfully!`) } } else if (connectOption === 'remote') { diff --git a/src/eth/command/network/check.ts b/src/eth/command/network/check.ts index 3a722e2..299095b 100644 --- a/src/eth/command/network/check.ts +++ b/src/eth/command/network/check.ts @@ -4,10 +4,11 @@ import prompts from 'prompts' import Network from '../../service/network' import { onCancel, ParamsError, ProcessError } from '../../../util/error' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'check' -export const desc = '確認 Quorum Node 資訊' +export const desc = '確認 Eth Network Node 資訊' interface OptType { interactive: boolean @@ -15,12 +16,23 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network check --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network check --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } export const handler = async (argv: Arguments) => { - const network = new Network(config, 'quorum') + const { networkType } = await prompts([ + { + type: 'select', + name: 'networkType', + message: 'What is your network?', + choices: getNetworkTypeChoices().map(choice => ({ + title: choice.title, + value: choice.title, + })), + }, + ]) + const network = new Network(config, networkType) if (argv.interactive) { const node: string = await (async () => { @@ -53,10 +65,10 @@ export const handler = async (argv: Arguments) => { }, ], { onCancel }) - const spinner = ora('Quorum Network Check ...').start() + const spinner = ora(`${networkType} Network Check ...`).start() const result = await network.checkNode(node, method) - spinner.succeed(`Quorum Network Check Result: ${result}`) - spinner.succeed('Quorum Network Check Successfully!') + spinner.succeed(`${networkType} Network Check Result: ${result}`) + spinner.succeed(`${networkType} Network Check Successfully!`) } else { throw new ParamsError('Invalid params: Required parameter missing') } diff --git a/src/eth/command/network/create.ts b/src/eth/command/network/create.ts index 381a92e..7c48f3a 100644 --- a/src/eth/command/network/create.ts +++ b/src/eth/command/network/create.ts @@ -181,7 +181,7 @@ export const handler = async (argv: Arguments) => { return { networkType, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList } } else { const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM) - return defaultNetworkConfig(address, privateKey) + return defaultNetworkConfig(address, privateKey, networkType) } } )() diff --git a/src/eth/command/network/delete.ts b/src/eth/command/network/delete.ts index 58075c6..d8cf919 100644 --- a/src/eth/command/network/delete.ts +++ b/src/eth/command/network/delete.ts @@ -27,7 +27,7 @@ export const handler = async () => { const response = await prompts({ type: 'confirm', name: 'value', - message: '⚠️ The following processes will remove all network files. Confirm to delete Quorum Network?', + message: `⚠️ The following processes will remove all network files. Confirm to delete ${networkTypeWithBigFirstLetter} Network?`, initial: false, }, { onCancel }) diff --git a/src/eth/command/network/down.ts b/src/eth/command/network/down.ts index 90484e5..85b4540 100644 --- a/src/eth/command/network/down.ts +++ b/src/eth/command/network/down.ts @@ -23,6 +23,7 @@ export const handler = async (argv: Arguments) => { choices: getNetworkTypeChoices(), }, ]) + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) const network = new Network(config, networkType) let confirmDelete = true @@ -30,15 +31,15 @@ export const handler = async (argv: Arguments) => { const response = await prompts({ type: 'confirm', name: 'value', - message: `Confirm to down ${networkType} Network?`, + message: `Confirm to down ${networkTypeWithBigFirstLetter} Network?`, initial: false, }, { onCancel }) confirmDelete = response.value if (confirmDelete) { - const spinner = ora(`${networkType} Network Down ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Down ...`).start() await network.down() - spinner.succeed(`${networkType} Network Down Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Down Successfully!`) } } diff --git a/src/eth/command/network/generate.ts b/src/eth/command/network/generate.ts index fdac8b0..d7b5926 100644 --- a/src/eth/command/network/generate.ts +++ b/src/eth/command/network/generate.ts @@ -42,7 +42,7 @@ export const handler = async (argv: Arguments) => { const confirmDelete = (await prompts({ type: 'confirm', name: 'value', - message: '⚠️ Detecting quorum nodes already exists. The following processes will remove all existing files. Continue?', + message: `⚠️ Detecting ${networkTypeWithBigFirstLetter} nodes already exists. The following processes will remove all existing files. Continue?`, initial: false, }, { onCancel })).value if (confirmDelete) { diff --git a/src/eth/command/network/get.ts b/src/eth/command/network/get.ts index e6be8b0..cfb0c57 100644 --- a/src/eth/command/network/get.ts +++ b/src/eth/command/network/get.ts @@ -8,7 +8,7 @@ import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'get' -export const desc = '取得 Quorum 檔案資訊' +export const desc = '取得 EthNetwork 檔案資訊' interface OptType { interactive: boolean @@ -16,7 +16,7 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network get --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network get --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } diff --git a/src/eth/command/network/join.ts b/src/eth/command/network/join.ts index cc936d9..ae035c5 100644 --- a/src/eth/command/network/join.ts +++ b/src/eth/command/network/join.ts @@ -9,7 +9,7 @@ import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'join' -export const desc = '選擇現有節點加入 Quorum Network' +export const desc = '選擇現有節點加入 Eth Network' interface OptType { interactive: boolean @@ -17,7 +17,7 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network join --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network join --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } @@ -56,21 +56,22 @@ export const handler = async (argv: Arguments) => { { type: 'text', name: 'ipAddress', - message: 'Provide the ip address of Quorum network you want to join', + message: 'Provide the ip address of network you want to join', }, { type: 'text', name: 'genesisJson', - message: 'Paste the genesis.json file of Quorum network you want to join', + message: 'Paste the genesis.json file of network you want to join', }, { type: 'text', name: 'staticNodesJson', - message: 'Paste the static-nodes.json file of Quorum network you want to join', + message: 'Paste the static-nodes.json file of network you want to join', }, ], { onCancel }) const joinNodeConfig: JoinNodeType = { + networkType: networkType, node: node, ipAddress: ipAddress, genesisJson: JSON.parse(genesisJson), diff --git a/src/eth/command/network/up.ts b/src/eth/command/network/up.ts index 0ab69ee..303c72b 100644 --- a/src/eth/command/network/up.ts +++ b/src/eth/command/network/up.ts @@ -8,7 +8,7 @@ import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'up' -export const desc = '啟動現有的 Quorum Network' +export const desc = '啟動現有的 Eth Network' interface OptType { interactive: boolean @@ -16,8 +16,8 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network up --interactive', 'Cathay BDK 互動式問答') - .example('bdk quorum network up --all', '啟動 BDK 資料夾下現有的 Quorum Network') + .example('bdk eth network up --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network up --all', '啟動 BDK 資料夾下現有的 Eth Network') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) .option('all', { type: 'boolean', description: '是否啟動所有節點', alias: 'a' }) } diff --git a/src/eth/config/network.type.ts b/src/eth/config/network.type.ts index ba9499a..9f8990f 100644 --- a/src/eth/config/network.type.ts +++ b/src/eth/config/network.type.ts @@ -10,7 +10,7 @@ export interface NetworkConfigType { chainId: number, peerPort: number, bootnode: boolean, - nodeEncode: string + nodeEncode: string, ) => string[] } diff --git a/src/eth/instance/infra/InfraRunner.interface.ts b/src/eth/instance/infra/InfraRunner.interface.ts index 57463a8..923b250 100644 --- a/src/eth/instance/infra/InfraRunner.interface.ts +++ b/src/eth/instance/infra/InfraRunner.interface.ts @@ -35,6 +35,8 @@ export interface KubernetesInfraRunner { wait(job: string, namespace: string): Promise deleteDeploymentAndService(payload: ClusterDeleteType): Promise listAllRelease(namespace: string): Promise + forceDeleteNamespace(namespace: string): Promise + deleteNamespace(namespace: string): Promise } // Strategy diff --git a/src/eth/instance/infra/kubernetes/runner.ts b/src/eth/instance/infra/kubernetes/runner.ts index a6e2d36..86b3d2b 100644 --- a/src/eth/instance/infra/kubernetes/runner.ts +++ b/src/eth/instance/infra/kubernetes/runner.ts @@ -50,6 +50,16 @@ export class Runner implements KubernetesInfraRunner { return { stdout: '' } } + public forceDeleteNamespace = async (namespace: string): Promise => { + await this.runKubectl(['delete', 'namespace', namespace, '--force']) + return { stdout: '' } + } + + public deleteNamespace = async (namespace: string): Promise => { + await this.runKubectl(['delete', 'namespace', namespace]) + return { stdout: '' } + } + public deleteAll = async (payload: K8SRunCommandType): Promise => { await this.runKubectl(['delete', 'all', '--all', '-n', payload.namespace]) return { stdout: '' } diff --git a/src/eth/instance/kubernetesCluster.ts b/src/eth/instance/kubernetesCluster.ts index 22ae7fb..b2e2c66 100644 --- a/src/eth/instance/kubernetesCluster.ts +++ b/src/eth/instance/kubernetesCluster.ts @@ -20,7 +20,18 @@ export default class KubernetesInstance extends AbstractInstance { public async delete (payload: ClusterDeleteType) { logger.debug('Kubernetes instance delete') if (this.kubernetesInfra !== undefined) { - return await this.kubernetesInfra.deleteDeploymentAndService(payload) + try { + await this.kubernetesInfra.deleteNamespace(payload.namespace) + logger.info(`Successfully deleted namespace ${payload.namespace}`) + } catch (error) { + logger.error(`Failed to delete namespace ${payload.namespace}:`, error) + try { + await this.kubernetesInfra.forceDeleteNamespace(payload.namespace) + logger.info(`Successfully force deleted namespace ${payload.namespace}`) + } catch (forceError) { + logger.error(`Failed to force delete namespace ${payload.namespace}:`, forceError) + } + } } } @@ -37,4 +48,18 @@ export default class KubernetesInstance extends AbstractInstance { return await this.kubernetesInfra.wait(job, namespace) } } + + public async deleteNamespace (namespace: string): Promise { + logger.debug(`Deleting namespace ${namespace}`) + if (this.kubernetesInfra !== undefined) { + await this.kubernetesInfra.deleteNamespace(namespace) + } + } + + public async forceDeleteNamespace (namespace: string): Promise { + logger.debug(`Force deleting namespace ${namespace}`) + if (this.kubernetesInfra !== undefined) { + await this.kubernetesInfra.forceDeleteNamespace(namespace) + } + } } diff --git a/src/eth/model/defaultNetworkConfig.ts b/src/eth/model/defaultNetworkConfig.ts index 4474844..0a84cce 100644 --- a/src/eth/model/defaultNetworkConfig.ts +++ b/src/eth/model/defaultNetworkConfig.ts @@ -1,7 +1,8 @@ import { NetworkCreateType } from './type/network.type' import ora from 'ora' +import { NetworkType } from '../config/network.type' -export function defaultNetworkConfig (address: string, privateKey: string) { +export function defaultNetworkConfig (address: string, privateKey: string, networkType: NetworkType) { ora().stopAndPersist({ text: `Your wallet address: 0x${address}`, symbol: '🔑', @@ -12,6 +13,7 @@ export function defaultNetworkConfig (address: string, privateKey: string) { }) const networkConfig: NetworkCreateType = { + networkType, chainId: 81712, validatorNumber: 4, memberNumber: 0, diff --git a/src/eth/model/type/kubernetes.type.ts b/src/eth/model/type/kubernetes.type.ts index 22d04f2..92e99c0 100644 --- a/src/eth/model/type/kubernetes.type.ts +++ b/src/eth/model/type/kubernetes.type.ts @@ -14,6 +14,7 @@ export interface ClusterDeleteType { name: string namespace: string } + export interface ClusterCreateType extends NetworkCreateType { networkType: NetworkType provider: string diff --git a/src/eth/service/cluster.ts b/src/eth/service/cluster.ts index 1d32294..4547cff 100644 --- a/src/eth/service/cluster.ts +++ b/src/eth/service/cluster.ts @@ -6,7 +6,7 @@ import KubernetesInstance from '../instance/kubernetesCluster' import { ClusterCreateType, ClusterGenerateType } from '../model/type/kubernetes.type' import { GenesisConfigYaml, ValidatorConfigYaml, MemberConfigYaml } from '../model/yaml/helm-chart' import { DockerResultType } from '../instance/infra/InfraRunner.interface' - +import { NetworkType } from '../config/network.type' export default class Cluster extends AbstractService { /** * @description Use helm create quorum template @@ -23,7 +23,6 @@ export default class Cluster extends AbstractService { genesisYaml.setProvider(provider, region) genesisYaml.setGenesis(networkType, chainId, validatorNumber) this.bdkFile.createGenesisChartValues(genesisYaml) - // custom namespace spinner.start('Helm install genesis chart') const genesisOutput = await k8s.install({ helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumGenesisChartPath() : this.bdkFile.getBesuGenesisChartPath(), @@ -138,27 +137,26 @@ export default class Cluster extends AbstractService { /** * @description Delete all quorum deployment and service */ - public async delete (): Promise { + public async delete (networkType: NetworkType): Promise { const k8s = new KubernetesInstance(this.config, this.infra, this.kubernetesInfra) - const releases = await this.getAllHelmRelease() - await Promise.all(releases.map(async (release: string) => { - try { - await k8s.delete({ name: release, namespace: 'quorum' }) - } catch (error) { - console.log(`Failed to delete release ${release} from quorum namespace:`) - } + try { + await k8s.deleteNamespace(networkType) + console.log(`Successfully deleted namespace ${networkType}`) + } catch (error) { + console.error(`Failed to delete namespace ${networkType}:`, error) try { - await k8s.delete({ name: release, namespace: 'besu' }) - } catch (error) { - console.log(`Failed to delete release ${release} from besu namespace: `) + await k8s.forceDeleteNamespace(networkType) + console.log(`Successfully force deleted namespace ${networkType}`) + } catch (forceError) { + console.error(`Failed to force delete namespace ${networkType}:`, forceError) } - })) + } } - private async getAllHelmRelease () { + private async getAllHelmRelease (networkType: NetworkType) { const k8s = new KubernetesInstance(this.config, this.infra, this.kubernetesInfra) - const releases = await k8s.listAllRelease('quorum') as DockerResultType + const releases = await k8s.listAllRelease(networkType) as DockerResultType return releases.stdout.split('\n').slice(1) } diff --git a/src/eth/service/network.ts b/src/eth/service/network.ts index 1717f56..55117c3 100644 --- a/src/eth/service/network.ts +++ b/src/eth/service/network.ts @@ -36,7 +36,7 @@ export default class Network extends AbstractService { alloc[`0x${x.account.replace(/^0x/, '').toLowerCase()}`] = { balance: x.amount } }) - const networkType = (networkCreateConfig.networkType || 'quorum') as NetworkType + const networkType = networkCreateConfig.networkType const genesisJsonYaml = new GenesisJsonYaml(networkType) genesisJsonYaml.addExtraData(extraData) genesisJsonYaml.addChainId(networkCreateConfig.chainId) @@ -111,7 +111,7 @@ export default class Network extends AbstractService { const bdkPath = this.bdkFile.getBdkPath() const enodeInfo = String(this.getNodeInfo(joinNodeConfig.node, 'enodeInfo')) const publicKey = String(this.getNodeInfo(joinNodeConfig.node, 'publicKey')) - + const networkType = joinNodeConfig.networkType for (let i = 0; i < joinNodeConfig.staticNodesJson.length; i += 1) { if (joinNodeConfig.staticNodesJson[i].includes(publicKey)) { staticNodesJson.push(enodeInfo) @@ -134,7 +134,7 @@ export default class Network extends AbstractService { const validatorDockerComposeYaml = new ValidatorDockerComposeYaml() // TODO: add bootnode selection - validatorDockerComposeYaml.addValidator(bdkPath, nodeNum, 8545 + nodeNum * 2, joinNodeConfig.genesisJson.config.chainId, 30303 + nodeNum, false, '', NetworkType.QUORUM) + validatorDockerComposeYaml.addValidator(bdkPath, nodeNum, 8545 + nodeNum * 2, joinNodeConfig.genesisJson.config.chainId, 30303 + nodeNum, false, '', networkType) this.createNetworkInfoJson(networkInfo, `http://validator${nodeNum}:${8545 + nodeNum * 2}`) this.bdkFile.createValidatorDockerComposeYaml(validatorDockerComposeYaml) @@ -151,7 +151,7 @@ export default class Network extends AbstractService { const memberDockerComposeYaml = new MemberDockerComposeYaml() // TODO: add bootnode selection - memberDockerComposeYaml.addMember(bdkPath, nodeNum, 8645 + nodeNum * 2, joinNodeConfig.genesisJson.config.chainId, 30403 + nodeNum, false, '', NetworkType.QUORUM) + memberDockerComposeYaml.addMember(bdkPath, nodeNum, 8645 + nodeNum * 2, joinNodeConfig.genesisJson.config.chainId, 30403 + nodeNum, false, '', networkType) this.createNetworkInfoJson(networkInfo, `http://member${nodeNum}:${8645 + nodeNum * 2}`) this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml) @@ -255,7 +255,7 @@ export default class Network extends AbstractService { this.bdkFile.createNetworkInfoJson(networkInfo) } - public async addValidatorLocal () { + public async addValidatorLocal (networkType: NetworkType) { const networkInfo: NetworkInfoItem[] = await this.bdkFile.getNetworkInfoJson() // count validator number const validatorCount = parseInt(await this.quorumCommand('istanbul.getValidators().length', 'validator0')) @@ -287,7 +287,7 @@ export default class Network extends AbstractService { this.bdkFile.copyStaticNodesJsonToValidator(i) this.bdkFile.copyPermissionedNodesJsonToValidator(i) // TODO: add bootnode selection - validatorDockerComposeYaml.addValidator(this.bdkFile.getBdkPath(), i, 8545 + i * 2, chainId, 30303 + i, false, '', NetworkType.QUORUM) + validatorDockerComposeYaml.addValidator(this.bdkFile.getBdkPath(), i, 8545 + i * 2, chainId, 30303 + i, false, '', networkType) this.createNetworkInfoJson(networkInfo, `http://validator${i}:${8545 + i * 2}`) } this.bdkFile.createValidatorDockerComposeYaml(validatorDockerComposeYaml) @@ -306,7 +306,7 @@ export default class Network extends AbstractService { return validatorNum } - public async addMemberLocal () { + public async addMemberLocal (networkType: NetworkType) { const networkInfo: NetworkInfoItem[] = await this.bdkFile.getNetworkInfoJson() // count member number const memberCount = (await this.bdkFile.getExportFiles().filter(file => file.match(/(member)[0-9]+/g))).length @@ -341,7 +341,7 @@ export default class Network extends AbstractService { this.bdkFile.copyStaticNodesJsonToMember(i) this.bdkFile.copyPermissionedNodesJsonToMember(i) // TODO: add bootnode selection - memberDockerComposeYaml.addMember(this.bdkFile.getBdkPath(), i, 8645 + i * 2, chainId, 30403 + i, false, '', NetworkType.QUORUM) + memberDockerComposeYaml.addMember(this.bdkFile.getBdkPath(), i, 8645 + i * 2, chainId, 30403 + i, false, '', networkType) this.createNetworkInfoJson(networkInfo, `http://member${i}:${8645 + i * 2}`) } this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml)