Skip to content

Commit

Permalink
feat: helm chart install & template prototype (#98)
Browse files Browse the repository at this point in the history
* feat: helm chart install & template prototype

feat: cluster ts

feat: helm charts install & template prototype

* feat(helm): create basic helm chart

* feat(helm): helm install in infra

* feat(bdk): bdk cluster apply network

* feat(bdk): bdk cluster generate network

* fix: generate yaml issues

* feat(helm): cloud native helm config

* feat(helm): aws region choice

* feat(helm): bdk network migrate with loadbalancer

* feat(bdk): bdk quorum cluster delete network

* docs(cluster): write cluster docs

* chore: fix command typo and wrong example

* fix: cluster generate template func
  • Loading branch information
kidneyweakx authored Mar 18, 2024
1 parent 00a7e17 commit a49479f
Show file tree
Hide file tree
Showing 48 changed files with 3,032 additions and 11 deletions.
31 changes: 31 additions & 0 deletions docs/quorum/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,34 @@ Description: 匯入現有的 Quorum Network
| --help | boolean | Show help | | |
| --version | boolean | Show version number | | |
| -i, --interactive | boolean | 是否使用 Cathay BDK 互動式問答 | | |

## Cluster

### `bdk quorum cluster apply`

Description: 產生 Quorum Cluster 所需的相關設定檔案並建立網路

| Options | Type | Description | Required | Default |
| --------------------- | :-----: | ------------------------------ | :------: | ------- |
| --help | boolean | Show help | | |
| --version | boolean | Show version number | | |

### `bdk quorum cluster delete`

Description: 刪除現有的 Quorum Cluster 網路

| Options | Type | Description | Required | Default |
| --------------------- | :-----: | ------------------------------ | :------: | ------- |
| --help | boolean | Show help | | |
| --version | boolean | Show version number | | |
| -i, --interactive | boolean | 是否使用 Cathay BDK 互動式問答 | | |

### `bdk quorum cluster generate`

Description: 產生 Quorum Cluster 所需的相關設定檔案

| Options | Type | Description | Required | Default |
| --------------------- | :-----: | ------------------------------ | :------: | ------- |
| --help | boolean | Show help | | |
| --version | boolean | Show version number | | |
| -i, --interactive | boolean | 是否使用 Cathay BDK 互動式問答 | | |
46 changes: 46 additions & 0 deletions docs/quorum/EXAMPLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [建立 Blockscout Explorer](#建立-blockscout-explorer)
- [加入 Remote 節點](#加入-remote-節點)
- [備份還原 Node](#備份還原-node)
- [建立 Cluster](#建立-cluster)

## 確認 BDK 安裝狀態

Expand Down Expand Up @@ -138,4 +139,49 @@ bdk quorum backup import -i
```bash
# 還原後需透過以下指令,來啟動該備份的節點
bdk quorum network up --all
```

## 建立 Cluster

先確保電腦安裝以下套件 `kubectl`, `helm`, `docker`
```bash
kubectl version
helm version
docker version
```
該範例以 `minikube` 做為本機建立的範例

### Step 1. 建立本地 Cluster

```bash
minikube start --memory 11384 --cpus 2
# 確認目前的 cluster 為 minikube
kubectl config current-context
```

### Step 2. 建立 K8S 網路
```bash
bdk quorum cluster apply -i
```
- `What is your cloud provider?` 選擇 `GCP/local`
- `What is your chain id?` 選擇 81712
- `How many validator do you want?` 選擇 4
- `How many member do you want?` 選擇 0
- `Do you already own a wallet?` false

這樣你的本地端的 quorum 網路就建立好了,如需連線及可用 `http://localhost:8545` 做連線
```bash
kubectl port-forward -n quorum svc/goquorum-node-validator-1 8545
```

### Step 3. 刪除 K8S 網路
```bash
bdk quorum cluster delete
```
按 'y' 刪除

## 產出 helm values 和資料於本地
如需直接使用 helm repo 來做 helm release 可利用以下 script
```bash
bdk quorum cluster generate -i
```
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ const npmBuild = spawnSync('npm', ['run', 'build-ts'])
console.log(`[+] child process exited with code ${npmBuild.status}`)
if (npmBuild.status !== 0) { console.error(`${npmBuild.output[1]}`); console.error('\x1b[31m%s\x1b[0m', npmBuild.stderr); exit(0) }

/**
* copy helm chart file
*/
console.log('[*] exec spawnSync: copy helm chart file')
const cp = spawnSync('cp', ['-r', 'src/quorum/instance/infra/kubernetes/charts', 'dist/quorum/instance/infra/kubernetes'])
console.log(`[+] child process exited with code ${cp.status}`)
if (cp.status !== 0) { console.error('\x1b[31m%s\x1b[0m', cp.stderr); exit(0) }

/**
* npm link/
*/
Expand Down
11 changes: 11 additions & 0 deletions src/quorum/command/cluster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Argv } from 'yargs'

export const command = 'cluster'

export const desc = '管理 Quorum cluster 的指令'

export const builder = (yargs: Argv) => {
return yargs.commandDir('cluster').demandCommand()
}

export const handler = {}
171 changes: 171 additions & 0 deletions src/quorum/command/cluster/apply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { Argv, Arguments } from 'yargs'
import { ethers } from 'ethers'
import config from '../../config'
import Cluster from '../../service/cluster'
import Wallet from '../../../wallet/service/wallet'
import { onCancel } from '../../../util/error'
import { ClusterCreateType } from '../../model/type/kubernetes.type'
import { WalletType } from '../../../wallet/model/type/wallet.type'
import { defaultNetworkConfig } from '../../model/defaultNetworkConfig'
import prompts from 'prompts'
import ora from 'ora'

export const command = 'apply'

export const desc = '產生 Quorum Cluster 所需的相關設定檔案並建立網路'

interface OptType {
interactive: boolean
}

export const builder = (yargs: Argv<OptType>) => {
return yargs
.example('bdk quorum cluster apply --interactive', 'Cathay BDK 互動式問答')
.option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' })
}

export const handler = async (argv: Arguments<OptType>) => {
const cluster = new Cluster(config)
const wallet = new Wallet()

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?',
initial: false,
}, { onCancel })).value
if (confirmDelete) {
const spinner = ora('Quorum Cluster Delete ...').start()
cluster.removeHelmChartFiles()
spinner.succeed('Remove all existing files!')
}
return confirmDelete
} else {
return true
}
})()

if (confirm) {
// network create
const clusterCreate: ClusterCreateType = await (async () => {
if (argv.interactive) {
const { provider } = await prompts({
type: 'select',
name: 'provider',
message: 'What is your cloud provider?',
choices: [
{
title: 'GCP/local',
value: 'local',
},
{
title: 'AWS',
value: 'aws',
},
{
title: 'Azure',
value: 'azure',
},
],
initial: 0,
}, { onCancel })

let region: string | undefined = ''
if (provider === 'aws') {
const { awsRegion } = await prompts({
type: 'text',
name: 'awsRegion',
message: 'What is your region?',
initial: 'ap-southeast-2',
}, { onCancel })
region = awsRegion
}

const { chainId, validatorNumber, memberNumber } = await prompts([
{
type: 'number',
name: 'chainId',
message: 'What is your chain id?',
min: 0,
initial: 81712,
},
{
type: 'number',
name: 'validatorNumber',
message: 'How many validator do you want?',
min: 1,
initial: 4,
},
{
type: 'number',
name: 'memberNumber',
message: 'How many member do you want?',
min: 0,
initial: 0,
},
], { onCancel })

const { walletOwner } = await prompts({
type: 'select',
name: 'walletOwner',
message: 'Do you already own a wallet?',
choices: [
{
title: 'true',
value: true,
},
{
title: 'false',
value: false,
},
],
initial: 1,
})

let walletAddress: string

if (walletOwner) {
const { address } = await prompts({
type: 'text',
name: 'address',
message: 'What is your wallet address?',
validate: walletAddress => ethers.utils.isAddress(walletAddress) ? true : 'Address not valid.',
}, { onCancel })

walletAddress = address
} else {
const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM)
walletAddress = address
ora().stopAndPersist({
text: `Your ${WalletType.ETHEREUM} wallet address: 0x${walletAddress}`,
symbol: '🔑',
})
ora().stopAndPersist({
text: `Wallet private key: ${privateKey}`,
symbol: '🔑',
})
}

const alloc = [{
account: walletAddress,
amount: '1000000000000000000000000000',
}]

const isBootNode = false
const bootNodeList: boolean[] = Array(validatorNumber + memberNumber).fill(false)

return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList }
} else {
const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM)
const config = defaultNetworkConfig(address, privateKey)
return { ...config, provider: 'local' }
}
})()
const spinner = ora('Quorum Cluster Apply ...').start()
await cluster.apply(clusterCreate, spinner)
spinner.succeed('Quorum Cluster Apply Successfully!')
}
}
49 changes: 49 additions & 0 deletions src/quorum/command/cluster/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Argv } from 'yargs'
import config from '../../config'
import Cluster from '../../service/cluster'
import { onCancel } from '../../../util/error'
import prompts from 'prompts'
import ora from 'ora'

export const command = 'delete'

export const desc = '刪除現有的 Quorum Cluster 網路'

interface OptType {
interactive: boolean
}

export const builder = (yargs: Argv<OptType>) => {
return yargs
.example('bdk quorum cluster delete', 'Cathay BDK 互動式問答')
}

export const handler = async () => {
const cluster = new Cluster(config)

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?',
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
}
})()

if (confirm) {
const spinner = ora('Deployments Under Namespace Quorum Delete ...').start()
await cluster.delete()
spinner.succeed('Quorum Cluster Delete Successfully!')
}
}
Loading

0 comments on commit a49479f

Please sign in to comment.