From 60fa4e475cf554162707dd2c69defa3c2c7dcc38 Mon Sep 17 00:00:00 2001 From: cheng-chun-yuan <83824908+cheng-chun-yuan@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:26:55 +0800 Subject: [PATCH 1/6] feat: rename the quorum file to eth --- src/{quorum => eth}/command/backup.ts | 0 src/{quorum => eth}/command/backup/export.ts | 0 src/{quorum => eth}/command/backup/import.ts | 0 src/{quorum => eth}/command/cluster.ts | 0 src/{quorum => eth}/command/cluster/apply.ts | 0 src/{quorum => eth}/command/cluster/delete.ts | 0 src/{quorum => eth}/command/cluster/generate.ts | 0 src/{quorum => eth}/command/explorer.ts | 0 src/{quorum => eth}/command/explorer/create.ts | 0 src/{quorum => eth}/command/explorer/delete.ts | 0 src/{quorum => eth}/command/network.ts | 0 src/{quorum => eth}/command/network/add.ts | 0 src/{quorum => eth}/command/network/check.ts | 0 src/{quorum => eth}/command/network/create.ts | 0 src/{quorum => eth}/command/network/delete.ts | 0 src/{quorum => eth}/command/network/down.ts | 0 src/{quorum => eth}/command/network/generate.ts | 0 src/{quorum => eth}/command/network/get.ts | 0 src/{quorum => eth}/command/network/join.ts | 0 src/{quorum => eth}/command/network/up.ts | 0 src/{quorum => eth}/config.ts | 0 src/{quorum => eth}/instance/Instance.abstract.ts | 0 src/{quorum => eth}/instance/bdkFile.ts | 0 src/{quorum => eth}/instance/explorer.ts | 0 src/{quorum => eth}/instance/infra/InfraRunner.interface.ts | 0 src/{quorum => eth}/instance/infra/docker/runner.ts | 0 src/{quorum => eth}/instance/infra/kubernetes/charts/LICENSE | 0 .../instance/infra/kubernetes/charts/bdk-network/Chart.yaml | 0 .../charts/bdk-network/templates/node-service-loadbalance.yaml | 0 .../instance/infra/kubernetes/charts/bdk-network/values.yaml | 0 .../instance/infra/kubernetes/charts/goquorum-genesis/.helmignore | 0 .../instance/infra/kubernetes/charts/goquorum-genesis/Chart.yaml | 0 .../kubernetes/charts/goquorum-genesis/templates/_helpers.tpl | 0 .../charts/goquorum-genesis/templates/genesis-job-cleanup.yaml | 0 .../charts/goquorum-genesis/templates/genesis-job-init.yaml | 0 .../goquorum-genesis/templates/genesis-service-account.yaml | 0 .../instance/infra/kubernetes/charts/goquorum-genesis/values.yaml | 0 .../instance/infra/kubernetes/charts/goquorum-node/.helmignore | 0 .../instance/infra/kubernetes/charts/goquorum-node/Chart.yaml | 0 .../infra/kubernetes/charts/goquorum-node/templates/_helpers.tpl | 0 .../charts/goquorum-node/templates/aws-secret-provider-class.yaml | 0 .../goquorum-node/templates/azure-secret-provider-class.yaml | 0 .../charts/goquorum-node/templates/node-hooks-pre-delete.yaml | 0 .../charts/goquorum-node/templates/node-hooks-pre-install.yaml | 0 .../goquorum-node/templates/node-hooks-service-account.yaml | 0 .../charts/goquorum-node/templates/node-service-account.yaml | 0 .../kubernetes/charts/goquorum-node/templates/node-service.yaml | 0 .../charts/goquorum-node/templates/node-servicemonitor.yaml | 0 .../charts/goquorum-node/templates/node-statefulset.yaml | 0 .../kubernetes/charts/goquorum-node/templates/node-storage.yaml | 0 .../instance/infra/kubernetes/charts/goquorum-node/values.yaml | 0 src/{quorum => eth}/instance/infra/kubernetes/runner.ts | 0 src/{quorum => eth}/instance/kubernetesCluster.ts | 0 src/{quorum => eth}/instance/member.ts | 0 src/{quorum => eth}/instance/validator.ts | 0 src/{quorum => eth}/model/defaultNetworkConfig.ts | 0 src/{quorum => eth}/model/type/config.type.ts | 0 src/{quorum => eth}/model/type/docker.type.ts | 0 src/{quorum => eth}/model/type/explorer.type.ts | 0 src/{quorum => eth}/model/type/kubernetes.type.ts | 0 src/{quorum => eth}/model/type/network.type.ts | 0 src/{quorum => eth}/model/yaml/bdkYaml.ts | 0 .../model/yaml/docker-compose/dockerComposeYaml.ts | 0 .../model/yaml/docker-compose/explorerDockerComposeYaml.ts | 0 .../model/yaml/docker-compose/memberDockerCompose.ts | 0 .../model/yaml/docker-compose/validatorDockerComposeYaml.ts | 0 src/{quorum => eth}/model/yaml/explorer/explorerConfigYaml.ts | 0 src/{quorum => eth}/model/yaml/helm-chart/blockscoutYaml.ts | 0 src/{quorum => eth}/model/yaml/helm-chart/genesisYaml.ts | 0 src/{quorum => eth}/model/yaml/helm-chart/helmChartYaml.ts | 0 src/{quorum => eth}/model/yaml/helm-chart/index.ts | 0 src/{quorum => eth}/model/yaml/helm-chart/memberYaml.ts | 0 src/{quorum => eth}/model/yaml/helm-chart/validatorYaml.ts | 0 src/{quorum => eth}/model/yaml/network/gensisJson.ts | 0 src/{quorum => eth}/quorum.ts | 0 src/{quorum => eth}/service/Service.abstract.ts | 0 src/{quorum => eth}/service/backup.ts | 0 src/{quorum => eth}/service/cluster.ts | 0 src/{quorum => eth}/service/explorer.ts | 0 src/{quorum => eth}/service/network.ts | 0 80 files changed, 0 insertions(+), 0 deletions(-) rename src/{quorum => eth}/command/backup.ts (100%) rename src/{quorum => eth}/command/backup/export.ts (100%) rename src/{quorum => eth}/command/backup/import.ts (100%) rename src/{quorum => eth}/command/cluster.ts (100%) rename src/{quorum => eth}/command/cluster/apply.ts (100%) rename src/{quorum => eth}/command/cluster/delete.ts (100%) rename src/{quorum => eth}/command/cluster/generate.ts (100%) rename src/{quorum => eth}/command/explorer.ts (100%) rename src/{quorum => eth}/command/explorer/create.ts (100%) rename src/{quorum => eth}/command/explorer/delete.ts (100%) rename src/{quorum => eth}/command/network.ts (100%) rename src/{quorum => eth}/command/network/add.ts (100%) rename src/{quorum => eth}/command/network/check.ts (100%) rename src/{quorum => eth}/command/network/create.ts (100%) rename src/{quorum => eth}/command/network/delete.ts (100%) rename src/{quorum => eth}/command/network/down.ts (100%) rename src/{quorum => eth}/command/network/generate.ts (100%) rename src/{quorum => eth}/command/network/get.ts (100%) rename src/{quorum => eth}/command/network/join.ts (100%) rename src/{quorum => eth}/command/network/up.ts (100%) rename src/{quorum => eth}/config.ts (100%) rename src/{quorum => eth}/instance/Instance.abstract.ts (100%) rename src/{quorum => eth}/instance/bdkFile.ts (100%) rename src/{quorum => eth}/instance/explorer.ts (100%) rename src/{quorum => eth}/instance/infra/InfraRunner.interface.ts (100%) rename src/{quorum => eth}/instance/infra/docker/runner.ts (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/LICENSE (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/bdk-network/Chart.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/bdk-network/templates/node-service-loadbalance.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/bdk-network/values.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/.helmignore (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/Chart.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/templates/_helpers.tpl (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-cleanup.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-init.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-service-account.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-genesis/values.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/.helmignore (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/Chart.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/_helpers.tpl (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/aws-secret-provider-class.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/azure-secret-provider-class.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-delete.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-install.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-service-account.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-service-account.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-service.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-servicemonitor.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-statefulset.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/templates/node-storage.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/charts/goquorum-node/values.yaml (100%) rename src/{quorum => eth}/instance/infra/kubernetes/runner.ts (100%) rename src/{quorum => eth}/instance/kubernetesCluster.ts (100%) rename src/{quorum => eth}/instance/member.ts (100%) rename src/{quorum => eth}/instance/validator.ts (100%) rename src/{quorum => eth}/model/defaultNetworkConfig.ts (100%) rename src/{quorum => eth}/model/type/config.type.ts (100%) rename src/{quorum => eth}/model/type/docker.type.ts (100%) rename src/{quorum => eth}/model/type/explorer.type.ts (100%) rename src/{quorum => eth}/model/type/kubernetes.type.ts (100%) rename src/{quorum => eth}/model/type/network.type.ts (100%) rename src/{quorum => eth}/model/yaml/bdkYaml.ts (100%) rename src/{quorum => eth}/model/yaml/docker-compose/dockerComposeYaml.ts (100%) rename src/{quorum => eth}/model/yaml/docker-compose/explorerDockerComposeYaml.ts (100%) rename src/{quorum => eth}/model/yaml/docker-compose/memberDockerCompose.ts (100%) rename src/{quorum => eth}/model/yaml/docker-compose/validatorDockerComposeYaml.ts (100%) rename src/{quorum => eth}/model/yaml/explorer/explorerConfigYaml.ts (100%) rename src/{quorum => eth}/model/yaml/helm-chart/blockscoutYaml.ts (100%) rename src/{quorum => eth}/model/yaml/helm-chart/genesisYaml.ts (100%) rename src/{quorum => eth}/model/yaml/helm-chart/helmChartYaml.ts (100%) rename src/{quorum => eth}/model/yaml/helm-chart/index.ts (100%) rename src/{quorum => eth}/model/yaml/helm-chart/memberYaml.ts (100%) rename src/{quorum => eth}/model/yaml/helm-chart/validatorYaml.ts (100%) rename src/{quorum => eth}/model/yaml/network/gensisJson.ts (100%) rename src/{quorum => eth}/quorum.ts (100%) rename src/{quorum => eth}/service/Service.abstract.ts (100%) rename src/{quorum => eth}/service/backup.ts (100%) rename src/{quorum => eth}/service/cluster.ts (100%) rename src/{quorum => eth}/service/explorer.ts (100%) rename src/{quorum => eth}/service/network.ts (100%) diff --git a/src/quorum/command/backup.ts b/src/eth/command/backup.ts similarity index 100% rename from src/quorum/command/backup.ts rename to src/eth/command/backup.ts diff --git a/src/quorum/command/backup/export.ts b/src/eth/command/backup/export.ts similarity index 100% rename from src/quorum/command/backup/export.ts rename to src/eth/command/backup/export.ts diff --git a/src/quorum/command/backup/import.ts b/src/eth/command/backup/import.ts similarity index 100% rename from src/quorum/command/backup/import.ts rename to src/eth/command/backup/import.ts diff --git a/src/quorum/command/cluster.ts b/src/eth/command/cluster.ts similarity index 100% rename from src/quorum/command/cluster.ts rename to src/eth/command/cluster.ts diff --git a/src/quorum/command/cluster/apply.ts b/src/eth/command/cluster/apply.ts similarity index 100% rename from src/quorum/command/cluster/apply.ts rename to src/eth/command/cluster/apply.ts diff --git a/src/quorum/command/cluster/delete.ts b/src/eth/command/cluster/delete.ts similarity index 100% rename from src/quorum/command/cluster/delete.ts rename to src/eth/command/cluster/delete.ts diff --git a/src/quorum/command/cluster/generate.ts b/src/eth/command/cluster/generate.ts similarity index 100% rename from src/quorum/command/cluster/generate.ts rename to src/eth/command/cluster/generate.ts diff --git a/src/quorum/command/explorer.ts b/src/eth/command/explorer.ts similarity index 100% rename from src/quorum/command/explorer.ts rename to src/eth/command/explorer.ts diff --git a/src/quorum/command/explorer/create.ts b/src/eth/command/explorer/create.ts similarity index 100% rename from src/quorum/command/explorer/create.ts rename to src/eth/command/explorer/create.ts diff --git a/src/quorum/command/explorer/delete.ts b/src/eth/command/explorer/delete.ts similarity index 100% rename from src/quorum/command/explorer/delete.ts rename to src/eth/command/explorer/delete.ts diff --git a/src/quorum/command/network.ts b/src/eth/command/network.ts similarity index 100% rename from src/quorum/command/network.ts rename to src/eth/command/network.ts diff --git a/src/quorum/command/network/add.ts b/src/eth/command/network/add.ts similarity index 100% rename from src/quorum/command/network/add.ts rename to src/eth/command/network/add.ts diff --git a/src/quorum/command/network/check.ts b/src/eth/command/network/check.ts similarity index 100% rename from src/quorum/command/network/check.ts rename to src/eth/command/network/check.ts diff --git a/src/quorum/command/network/create.ts b/src/eth/command/network/create.ts similarity index 100% rename from src/quorum/command/network/create.ts rename to src/eth/command/network/create.ts diff --git a/src/quorum/command/network/delete.ts b/src/eth/command/network/delete.ts similarity index 100% rename from src/quorum/command/network/delete.ts rename to src/eth/command/network/delete.ts diff --git a/src/quorum/command/network/down.ts b/src/eth/command/network/down.ts similarity index 100% rename from src/quorum/command/network/down.ts rename to src/eth/command/network/down.ts diff --git a/src/quorum/command/network/generate.ts b/src/eth/command/network/generate.ts similarity index 100% rename from src/quorum/command/network/generate.ts rename to src/eth/command/network/generate.ts diff --git a/src/quorum/command/network/get.ts b/src/eth/command/network/get.ts similarity index 100% rename from src/quorum/command/network/get.ts rename to src/eth/command/network/get.ts diff --git a/src/quorum/command/network/join.ts b/src/eth/command/network/join.ts similarity index 100% rename from src/quorum/command/network/join.ts rename to src/eth/command/network/join.ts diff --git a/src/quorum/command/network/up.ts b/src/eth/command/network/up.ts similarity index 100% rename from src/quorum/command/network/up.ts rename to src/eth/command/network/up.ts diff --git a/src/quorum/config.ts b/src/eth/config.ts similarity index 100% rename from src/quorum/config.ts rename to src/eth/config.ts diff --git a/src/quorum/instance/Instance.abstract.ts b/src/eth/instance/Instance.abstract.ts similarity index 100% rename from src/quorum/instance/Instance.abstract.ts rename to src/eth/instance/Instance.abstract.ts diff --git a/src/quorum/instance/bdkFile.ts b/src/eth/instance/bdkFile.ts similarity index 100% rename from src/quorum/instance/bdkFile.ts rename to src/eth/instance/bdkFile.ts diff --git a/src/quorum/instance/explorer.ts b/src/eth/instance/explorer.ts similarity index 100% rename from src/quorum/instance/explorer.ts rename to src/eth/instance/explorer.ts diff --git a/src/quorum/instance/infra/InfraRunner.interface.ts b/src/eth/instance/infra/InfraRunner.interface.ts similarity index 100% rename from src/quorum/instance/infra/InfraRunner.interface.ts rename to src/eth/instance/infra/InfraRunner.interface.ts diff --git a/src/quorum/instance/infra/docker/runner.ts b/src/eth/instance/infra/docker/runner.ts similarity index 100% rename from src/quorum/instance/infra/docker/runner.ts rename to src/eth/instance/infra/docker/runner.ts diff --git a/src/quorum/instance/infra/kubernetes/charts/LICENSE b/src/eth/instance/infra/kubernetes/charts/LICENSE similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/LICENSE rename to src/eth/instance/infra/kubernetes/charts/LICENSE diff --git a/src/quorum/instance/infra/kubernetes/charts/bdk-network/Chart.yaml b/src/eth/instance/infra/kubernetes/charts/bdk-network/Chart.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/bdk-network/Chart.yaml rename to src/eth/instance/infra/kubernetes/charts/bdk-network/Chart.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/bdk-network/templates/node-service-loadbalance.yaml b/src/eth/instance/infra/kubernetes/charts/bdk-network/templates/node-service-loadbalance.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/bdk-network/templates/node-service-loadbalance.yaml rename to src/eth/instance/infra/kubernetes/charts/bdk-network/templates/node-service-loadbalance.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/bdk-network/values.yaml b/src/eth/instance/infra/kubernetes/charts/bdk-network/values.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/bdk-network/values.yaml rename to src/eth/instance/infra/kubernetes/charts/bdk-network/values.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/.helmignore b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/.helmignore similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/.helmignore rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/.helmignore diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/Chart.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/Chart.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/Chart.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/Chart.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/_helpers.tpl b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/_helpers.tpl similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/_helpers.tpl rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/_helpers.tpl diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-cleanup.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-cleanup.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-cleanup.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-cleanup.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-init.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-init.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-init.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-job-init.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-service-account.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-service-account.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-service-account.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/templates/genesis-service-account.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/values.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-genesis/values.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-genesis/values.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-genesis/values.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/.helmignore b/src/eth/instance/infra/kubernetes/charts/goquorum-node/.helmignore similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/.helmignore rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/.helmignore diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/Chart.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/Chart.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/Chart.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/Chart.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/_helpers.tpl b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/_helpers.tpl similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/_helpers.tpl rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/_helpers.tpl diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/aws-secret-provider-class.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/aws-secret-provider-class.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/aws-secret-provider-class.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/aws-secret-provider-class.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/azure-secret-provider-class.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/azure-secret-provider-class.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/azure-secret-provider-class.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/azure-secret-provider-class.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-delete.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-delete.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-delete.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-delete.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-install.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-install.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-install.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-pre-install.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-service-account.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-service-account.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-service-account.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-hooks-service-account.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-service-account.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-service-account.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-service-account.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-service-account.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-service.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-service.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-service.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-service.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-servicemonitor.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-servicemonitor.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-servicemonitor.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-servicemonitor.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-statefulset.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-statefulset.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-statefulset.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-statefulset.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-storage.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-storage.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/templates/node-storage.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/templates/node-storage.yaml diff --git a/src/quorum/instance/infra/kubernetes/charts/goquorum-node/values.yaml b/src/eth/instance/infra/kubernetes/charts/goquorum-node/values.yaml similarity index 100% rename from src/quorum/instance/infra/kubernetes/charts/goquorum-node/values.yaml rename to src/eth/instance/infra/kubernetes/charts/goquorum-node/values.yaml diff --git a/src/quorum/instance/infra/kubernetes/runner.ts b/src/eth/instance/infra/kubernetes/runner.ts similarity index 100% rename from src/quorum/instance/infra/kubernetes/runner.ts rename to src/eth/instance/infra/kubernetes/runner.ts diff --git a/src/quorum/instance/kubernetesCluster.ts b/src/eth/instance/kubernetesCluster.ts similarity index 100% rename from src/quorum/instance/kubernetesCluster.ts rename to src/eth/instance/kubernetesCluster.ts diff --git a/src/quorum/instance/member.ts b/src/eth/instance/member.ts similarity index 100% rename from src/quorum/instance/member.ts rename to src/eth/instance/member.ts diff --git a/src/quorum/instance/validator.ts b/src/eth/instance/validator.ts similarity index 100% rename from src/quorum/instance/validator.ts rename to src/eth/instance/validator.ts diff --git a/src/quorum/model/defaultNetworkConfig.ts b/src/eth/model/defaultNetworkConfig.ts similarity index 100% rename from src/quorum/model/defaultNetworkConfig.ts rename to src/eth/model/defaultNetworkConfig.ts diff --git a/src/quorum/model/type/config.type.ts b/src/eth/model/type/config.type.ts similarity index 100% rename from src/quorum/model/type/config.type.ts rename to src/eth/model/type/config.type.ts diff --git a/src/quorum/model/type/docker.type.ts b/src/eth/model/type/docker.type.ts similarity index 100% rename from src/quorum/model/type/docker.type.ts rename to src/eth/model/type/docker.type.ts diff --git a/src/quorum/model/type/explorer.type.ts b/src/eth/model/type/explorer.type.ts similarity index 100% rename from src/quorum/model/type/explorer.type.ts rename to src/eth/model/type/explorer.type.ts diff --git a/src/quorum/model/type/kubernetes.type.ts b/src/eth/model/type/kubernetes.type.ts similarity index 100% rename from src/quorum/model/type/kubernetes.type.ts rename to src/eth/model/type/kubernetes.type.ts diff --git a/src/quorum/model/type/network.type.ts b/src/eth/model/type/network.type.ts similarity index 100% rename from src/quorum/model/type/network.type.ts rename to src/eth/model/type/network.type.ts diff --git a/src/quorum/model/yaml/bdkYaml.ts b/src/eth/model/yaml/bdkYaml.ts similarity index 100% rename from src/quorum/model/yaml/bdkYaml.ts rename to src/eth/model/yaml/bdkYaml.ts diff --git a/src/quorum/model/yaml/docker-compose/dockerComposeYaml.ts b/src/eth/model/yaml/docker-compose/dockerComposeYaml.ts similarity index 100% rename from src/quorum/model/yaml/docker-compose/dockerComposeYaml.ts rename to src/eth/model/yaml/docker-compose/dockerComposeYaml.ts diff --git a/src/quorum/model/yaml/docker-compose/explorerDockerComposeYaml.ts b/src/eth/model/yaml/docker-compose/explorerDockerComposeYaml.ts similarity index 100% rename from src/quorum/model/yaml/docker-compose/explorerDockerComposeYaml.ts rename to src/eth/model/yaml/docker-compose/explorerDockerComposeYaml.ts diff --git a/src/quorum/model/yaml/docker-compose/memberDockerCompose.ts b/src/eth/model/yaml/docker-compose/memberDockerCompose.ts similarity index 100% rename from src/quorum/model/yaml/docker-compose/memberDockerCompose.ts rename to src/eth/model/yaml/docker-compose/memberDockerCompose.ts diff --git a/src/quorum/model/yaml/docker-compose/validatorDockerComposeYaml.ts b/src/eth/model/yaml/docker-compose/validatorDockerComposeYaml.ts similarity index 100% rename from src/quorum/model/yaml/docker-compose/validatorDockerComposeYaml.ts rename to src/eth/model/yaml/docker-compose/validatorDockerComposeYaml.ts diff --git a/src/quorum/model/yaml/explorer/explorerConfigYaml.ts b/src/eth/model/yaml/explorer/explorerConfigYaml.ts similarity index 100% rename from src/quorum/model/yaml/explorer/explorerConfigYaml.ts rename to src/eth/model/yaml/explorer/explorerConfigYaml.ts diff --git a/src/quorum/model/yaml/helm-chart/blockscoutYaml.ts b/src/eth/model/yaml/helm-chart/blockscoutYaml.ts similarity index 100% rename from src/quorum/model/yaml/helm-chart/blockscoutYaml.ts rename to src/eth/model/yaml/helm-chart/blockscoutYaml.ts diff --git a/src/quorum/model/yaml/helm-chart/genesisYaml.ts b/src/eth/model/yaml/helm-chart/genesisYaml.ts similarity index 100% rename from src/quorum/model/yaml/helm-chart/genesisYaml.ts rename to src/eth/model/yaml/helm-chart/genesisYaml.ts diff --git a/src/quorum/model/yaml/helm-chart/helmChartYaml.ts b/src/eth/model/yaml/helm-chart/helmChartYaml.ts similarity index 100% rename from src/quorum/model/yaml/helm-chart/helmChartYaml.ts rename to src/eth/model/yaml/helm-chart/helmChartYaml.ts diff --git a/src/quorum/model/yaml/helm-chart/index.ts b/src/eth/model/yaml/helm-chart/index.ts similarity index 100% rename from src/quorum/model/yaml/helm-chart/index.ts rename to src/eth/model/yaml/helm-chart/index.ts diff --git a/src/quorum/model/yaml/helm-chart/memberYaml.ts b/src/eth/model/yaml/helm-chart/memberYaml.ts similarity index 100% rename from src/quorum/model/yaml/helm-chart/memberYaml.ts rename to src/eth/model/yaml/helm-chart/memberYaml.ts diff --git a/src/quorum/model/yaml/helm-chart/validatorYaml.ts b/src/eth/model/yaml/helm-chart/validatorYaml.ts similarity index 100% rename from src/quorum/model/yaml/helm-chart/validatorYaml.ts rename to src/eth/model/yaml/helm-chart/validatorYaml.ts diff --git a/src/quorum/model/yaml/network/gensisJson.ts b/src/eth/model/yaml/network/gensisJson.ts similarity index 100% rename from src/quorum/model/yaml/network/gensisJson.ts rename to src/eth/model/yaml/network/gensisJson.ts diff --git a/src/quorum/quorum.ts b/src/eth/quorum.ts similarity index 100% rename from src/quorum/quorum.ts rename to src/eth/quorum.ts diff --git a/src/quorum/service/Service.abstract.ts b/src/eth/service/Service.abstract.ts similarity index 100% rename from src/quorum/service/Service.abstract.ts rename to src/eth/service/Service.abstract.ts diff --git a/src/quorum/service/backup.ts b/src/eth/service/backup.ts similarity index 100% rename from src/quorum/service/backup.ts rename to src/eth/service/backup.ts diff --git a/src/quorum/service/cluster.ts b/src/eth/service/cluster.ts similarity index 100% rename from src/quorum/service/cluster.ts rename to src/eth/service/cluster.ts diff --git a/src/quorum/service/explorer.ts b/src/eth/service/explorer.ts similarity index 100% rename from src/quorum/service/explorer.ts rename to src/eth/service/explorer.ts diff --git a/src/quorum/service/network.ts b/src/eth/service/network.ts similarity index 100% rename from src/quorum/service/network.ts rename to src/eth/service/network.ts From b24bcab8e24abda3e95978eb3c6895557300cb7d Mon Sep 17 00:00:00 2001 From: cheng-chun-yuan <83824908+cheng-chun-yuan@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:43:59 +0800 Subject: [PATCH 2/6] fix: change the commandDir from quorum to eth, and rename test/quorum to test/eth --- .nycrc.json | 6 +++--- src/bdk.ts | 2 +- src/console.ts | 2 +- src/eth/command/backup.ts | 2 +- src/eth/command/cluster.ts | 2 +- src/eth/command/explorer.ts | 2 +- src/eth/command/network.ts | 2 +- src/eth/config.ts | 4 ++-- src/eth/eth.ts | 11 +++++++++++ src/eth/instance/infra/docker/runner.ts | 6 +++--- src/eth/quorum.ts | 11 ----------- src/util/error.ts | 4 ++-- src/wallet/service/wallet.ts | 2 +- test/{quorum => eth}/service/backup.test.ts | 8 ++++---- test/{quorum => eth}/service/explorer.test.ts | 8 ++++---- test/{quorum => eth}/service/network.test.ts | 6 +++--- 16 files changed, 39 insertions(+), 39 deletions(-) create mode 100644 src/eth/eth.ts delete mode 100644 src/eth/quorum.ts rename test/{quorum => eth}/service/backup.test.ts (95%) rename test/{quorum => eth}/service/explorer.test.ts (88%) rename test/{quorum => eth}/service/network.test.ts (98%) diff --git a/.nycrc.json b/.nycrc.json index 5a440f9b..65450ed1 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -8,13 +8,13 @@ "statements": 0, "include": [ "src/fabric/service/**.ts", - "src/quorum/service/**.ts", + "src/eth/service/**.ts", "src/wallet/service/**.ts" ], "exclude": [ "src/fabric/service/Service.abstract.ts", - "src/quorum/service/Service.abstract.ts", - "src/quorum/service/network.ts" + "src/eth/service/Service.abstract.ts", + "src/eth/service/network.ts" ], "reporter": [ "text-summary", diff --git a/src/bdk.ts b/src/bdk.ts index 1c6bcbd0..b77207d9 100755 --- a/src/bdk.ts +++ b/src/bdk.ts @@ -25,7 +25,7 @@ const argv = yargs return true }) .commandDir('fabric') - .commandDir('quorum') + .commandDir('eth') .commandDir('wallet') .commandDir('hello') .commandDir('dashboard') diff --git a/src/console.ts b/src/console.ts index 75e5ec69..d6a6c1e4 100644 --- a/src/console.ts +++ b/src/console.ts @@ -44,7 +44,7 @@ if (npmBuild.status !== 0) { console.error(`${npmBuild.output[1]}`); console.err * 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']) +const cp = spawnSync('cp', ['-r', 'src/eth/instance/infra/kubernetes/charts', 'dist/eth/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) } diff --git a/src/eth/command/backup.ts b/src/eth/command/backup.ts index 5aac64d2..880c52d8 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 = '管理 Quorum backup 的指令' +export const desc = '管理 Eth 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 8758195d..5cda8ba2 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 = '管理 Quorum cluster 的指令' +export const desc = '管理 Eth cluster 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('cluster').demandCommand() diff --git a/src/eth/command/explorer.ts b/src/eth/command/explorer.ts index 180a357f..70c00bbf 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 = '管理 Quorum explorer 的指令' +export const desc = '管理 Eth explorer 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('explorer').demandCommand() diff --git a/src/eth/command/network.ts b/src/eth/command/network.ts index d2d48ceb..ebff5742 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 = '管理 Quorum network 的指令' +export const desc = '管理 Eth network 的指令' export const builder = (yargs: Argv) => { return yargs.commandDir('network').demandCommand() diff --git a/src/eth/config.ts b/src/eth/config.ts index 047b1d64..3aa5ad67 100644 --- a/src/eth/config.ts +++ b/src/eth/config.ts @@ -2,7 +2,7 @@ import dotenv from 'dotenv' import os from 'os' import { EnvironmentEnum, NodeTypeEnum } from './model/type/config.type' -const bdkPath = process.env.BDK_PATH || `${process.env.HOME}/.bdk/quorum` +const bdkPath = process.env.BDK_PATH || `${process.env.HOME}/.bdk/eth` dotenv.config({ path: `${bdkPath}/.env` }) /** @@ -62,7 +62,7 @@ const config: Config = { dockerHostPath: process.env.BDK_DOCKER_HOST_PATH || bdkPath, dockerPath: '/tmp', }, - networkName: process.env.BDK_QUORUM_NETWORK_NAME || 'bdk-quorum-network', + networkName: process.env.BDK_ETH_NETWORK_NAME || 'bdk-quorum-network', nodeType: nodeType, hostname: process.env.BDK_HOSTNAME || '', UID: process.env.UID === undefined ? os.userInfo().uid : parseInt(process.env.UID, 10), diff --git a/src/eth/eth.ts b/src/eth/eth.ts new file mode 100644 index 00000000..cbe89061 --- /dev/null +++ b/src/eth/eth.ts @@ -0,0 +1,11 @@ +import { Argv } from 'yargs' + +export const command = 'eth' + +export const desc = '管理 Eth 的指令' + +export const builder = (yargs: Argv) => { + return yargs.commandDir('../eth/command').demandCommand() +} + +export const handler = {} diff --git a/src/eth/instance/infra/docker/runner.ts b/src/eth/instance/infra/docker/runner.ts index ba1702d4..a4ee0d81 100644 --- a/src/eth/instance/infra/docker/runner.ts +++ b/src/eth/instance/infra/docker/runner.ts @@ -6,7 +6,7 @@ import Dockerode from 'dockerode' import { logger } from '../../../../util/logger' import { DockerCreateOptionsType, DockerStartOptionsType, DockerRunCommandType } from '../../../model/type/docker.type' import config from '../../../config' -import { DockerError, QuorumContainerError } from '../../../../util/error' +import { DockerError, EthContainerError } from '../../../../util/error' import { DockerResultType, InfraRunner } from '../InfraRunner.interface' import { DockerComposeYamlInterface } from '../../../model/yaml/docker-compose/dockerComposeYaml' @@ -69,11 +69,11 @@ export class Runner implements InfraRunner { logger.silly(`run command output: \n${stdout}`) logger.debug(`docker run\n image: ${image}\n commands: ${commands.join(' ')}`) if (dockerRunResult[0].StatusCode !== 0 && !ignoreError) { - throw new QuorumContainerError(`[x] [in-docker-container error] ${stdout.split('\r\n').filter(x => x.match(/error/i) || stdout)}`, stdout) + throw new EthContainerError(`[x] [in-docker-container error] ${stdout.split('\r\n').filter(x => x.match(/error/i) || stdout)}`, stdout) } return { statusCode: dockerRunResult[0].StatusCode, stdout: stdout.toString() } } catch (e: any) { - if (e instanceof QuorumContainerError) { throw e } + if (e instanceof EthContainerError) { throw e } throw new DockerError(`[x] command [docker run]:${e.message}`) } } diff --git a/src/eth/quorum.ts b/src/eth/quorum.ts deleted file mode 100644 index 04824bb9..00000000 --- a/src/eth/quorum.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Argv } from 'yargs' - -export const command = 'quorum' - -export const desc = '管理 Quorum 的指令' - -export const builder = (yargs: Argv) => { - return yargs.commandDir('../quorum/command').demandCommand() -} - -export const handler = {} diff --git a/src/util/error.ts b/src/util/error.ts index e6bc0fb4..4b73ffa8 100644 --- a/src/util/error.ts +++ b/src/util/error.ts @@ -17,7 +17,7 @@ export class FabricContainerError extends BdkError { this.stdout = stdout } } -export class QuorumContainerError extends BdkError { +export class EthContainerError extends BdkError { public stdout: string constructor (message: string, stdout: string) { super(message) @@ -35,7 +35,7 @@ export const onCancel = (prompt: prompts.PromptObject, answers: any) => export const errorHandler = (err: Error) => { if (err instanceof FabricContainerError) { logger.error(err.message) - } else if (err instanceof QuorumContainerError) { + } else if (err instanceof EthContainerError) { logger.error(err.message) } else if (err instanceof BdkError) { logger.error(err.message) diff --git a/src/wallet/service/wallet.ts b/src/wallet/service/wallet.ts index aecd3e65..1ddcdac7 100644 --- a/src/wallet/service/wallet.ts +++ b/src/wallet/service/wallet.ts @@ -3,7 +3,7 @@ import { WalletCreateType, WalletType } from '../model/type/wallet.type' export default class Wallet { /** - * @description 建立 quorum network + * @description 建立 eth network */ public create (walletCreateConfig: WalletCreateType) { const { address, privateKey } = this.createWalletAddress(walletCreateConfig.type) diff --git a/test/quorum/service/backup.test.ts b/test/eth/service/backup.test.ts similarity index 95% rename from test/quorum/service/backup.test.ts rename to test/eth/service/backup.test.ts index 0c7aeef8..509c2937 100644 --- a/test/quorum/service/backup.test.ts +++ b/test/eth/service/backup.test.ts @@ -4,11 +4,11 @@ import assert from 'assert' import tar from 'tar' import sinon from 'sinon' import { resolve } from 'path' -import config from '../../../src/quorum/config' -import Backup from '../../../src/quorum/service/backup' -import Network from '../../../src/quorum/service/network' +import config from '../../../src/eth/config' +import Backup from '../../../src/eth/service/backup' +import Network from '../../../src/eth/service/network' import { BackupError, sleep } from '../../../src/util' -import { NetworkCreateType } from '../../../src/quorum/model/type/network.type' +import { NetworkCreateType } from '../../../src/eth/model/type/network.type' // write a test for the backup class describe('Quorum.Backup', function () { diff --git a/test/quorum/service/explorer.test.ts b/test/eth/service/explorer.test.ts similarity index 88% rename from test/quorum/service/explorer.test.ts rename to test/eth/service/explorer.test.ts index 312ec160..1447b53f 100644 --- a/test/quorum/service/explorer.test.ts +++ b/test/eth/service/explorer.test.ts @@ -1,10 +1,10 @@ /* global describe, it */ import Dockerode from 'dockerode' import assert from 'assert' -import Network from '../../../src/quorum/service/network' -import Explorer from '../../../src/quorum/service/explorer' -import config from '../../../src/quorum/config' -import { ExplorerCreateType } from '../../../src/quorum/model/type/explorer.type' +import Network from '../../../src/eth/service/network' +import Explorer from '../../../src/eth/service/explorer' +import config from '../../../src/eth/config' +import { ExplorerCreateType } from '../../../src/eth/model/type/explorer.type' describe('Quorum.Explorer.Service', function () { this.timeout(600000) diff --git a/test/quorum/service/network.test.ts b/test/eth/service/network.test.ts similarity index 98% rename from test/quorum/service/network.test.ts rename to test/eth/service/network.test.ts index ca30be37..0cd7e24c 100644 --- a/test/quorum/service/network.test.ts +++ b/test/eth/service/network.test.ts @@ -2,12 +2,12 @@ import Dockerode from 'dockerode' import assert from 'assert' import sinon from 'sinon' -import Network from '../../../src/quorum/service/network' -import config from '../../../src/quorum/config' +import Network from '../../../src/eth/service/network' +import config from '../../../src/eth/config' import fs from 'fs' import { resolve } from 'path' import { sleep, TimeLimitError } from '../../../src/util' -import { JoinNodeType } from '../../../src/quorum/model/type/network.type' +import { JoinNodeType } from '../../../src/eth/model/type/network.type' import Wallet from '../../../src/wallet/service/wallet' import { WalletType } from '../../../src/wallet/model/type/wallet.type' From 15acd92e7339406967be4b913c4ac9cd4d34be50 Mon Sep 17 00:00:00 2001 From: cheng-chun-yuan <83824908+cheng-chun-yuan@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:39:57 +0800 Subject: [PATCH 3/6] feat: create config file to store genesisfile, dockerComposed of member and validator and add bdk eth network with add, create, delete, down, generate, get, join, up --- src/eth/command/backup/export.ts | 27 +++++++--- src/eth/command/backup/import.ts | 20 ++++++-- src/eth/command/cluster/apply.ts | 2 +- src/eth/command/cluster/delete.ts | 2 +- src/eth/command/cluster/generate.ts | 2 +- src/eth/command/explorer/create.ts | 4 +- src/eth/command/explorer/delete.ts | 2 +- src/eth/command/network/add.ts | 28 ++++++---- src/eth/command/network/check.ts | 2 +- src/eth/command/network/create.ts | 33 ++++++++---- src/eth/command/network/delete.ts | 21 +++++--- src/eth/command/network/down.ts | 19 +++++-- src/eth/command/network/generate.ts | 24 ++++++--- src/eth/command/network/get.ts | 24 ++++++--- src/eth/command/network/join.ts | 16 ++++-- src/eth/command/network/up.ts | 20 ++++++-- src/eth/config.ts | 4 +- src/eth/config/besu/besuGenesisConfig.ts | 34 +++++++++++++ src/eth/config/besu/besuMemberConfig.ts | 29 +++++++++++ src/eth/config/besu/besuValidatorConfig.ts | 13 +++++ src/eth/config/network.type.ts | 22 ++++++++ src/eth/config/networkConfigLoader.ts | 47 +++++++++++++++++ src/eth/config/quorum/quorumGenesisConfig.ts | 46 +++++++++++++++++ src/eth/config/quorum/quorumMemberConfig.ts | 13 +++++ .../config/quorum/quorumValidatorConfig.ts | 13 +++++ src/eth/model/type/network.type.ts | 14 ++--- .../docker-compose/memberDockerCompose.ts | 31 +++++++---- .../validatorDockerComposeYaml.ts | 30 ++++++++--- src/eth/model/yaml/network/gensisJson.ts | 51 +++---------------- src/eth/service/Service.abstract.ts | 8 ++- src/eth/service/backup.ts | 6 +-- src/eth/service/network.ts | 20 ++++---- test/eth/service/backup.test.ts | 4 +- test/eth/service/explorer.test.ts | 4 +- test/eth/service/network.test.ts | 2 +- 35 files changed, 475 insertions(+), 162 deletions(-) create mode 100644 src/eth/config/besu/besuGenesisConfig.ts create mode 100644 src/eth/config/besu/besuMemberConfig.ts create mode 100644 src/eth/config/besu/besuValidatorConfig.ts create mode 100644 src/eth/config/network.type.ts create mode 100644 src/eth/config/networkConfigLoader.ts create mode 100644 src/eth/config/quorum/quorumGenesisConfig.ts create mode 100644 src/eth/config/quorum/quorumMemberConfig.ts create mode 100644 src/eth/config/quorum/quorumValidatorConfig.ts diff --git a/src/eth/command/backup/export.ts b/src/eth/command/backup/export.ts index 934956ca..df083178 100644 --- a/src/eth/command/backup/export.ts +++ b/src/eth/command/backup/export.ts @@ -4,10 +4,12 @@ import Backup from '../../service/backup' import { onCancel, ParamsError, ProcessError } from '../../../util/error' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'export' -export const desc = '匯出現有的 Quorum Network' +export const desc = '匯出現有的 Eth Network' + interface OptType { interactive: boolean @@ -15,19 +17,28 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum backup export --interactive', 'Cathay BDK 互動式問答') - .example('bdk quorum backup export --all', '備份 BDK 資料夾下所有 Quorum Network 資料') + .example('bdk eth backup export --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth backup export --all', '備份所選 BDK 資料夾下所有 Eth Network 資料') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) .option('all', { type: 'boolean', description: '是否備份所有資料', alias: 'a' }) } export const handler = async (argv: Arguments) => { - const backup = new Backup(config) + 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 backup = new Backup(config, networkType) if (argv.all) { - const spinner = ora('Quorum Network Export All ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Export All ...`).start() await backup.exportAll() - spinner.succeed('Quorum Network Export All Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Export All Successfully!`) } else if (argv.interactive) { const node: string = await (async () => { const nodeList = backup.getExportItems() @@ -43,9 +54,9 @@ export const handler = async (argv: Arguments) => { } })() - const spinner = ora(`Quorum Network Export ${node} ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Export ${node} ...`).start() await backup.export(node) - spinner.succeed(`Quorum Network Export ${node} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Export ${node} Successfully!`) } else { throw new ParamsError('Invalid params: Required parameter missing') } diff --git a/src/eth/command/backup/import.ts b/src/eth/command/backup/import.ts index 5fbb0be3..8eb13f71 100644 --- a/src/eth/command/backup/import.ts +++ b/src/eth/command/backup/import.ts @@ -4,10 +4,11 @@ import Backup from '../../service/backup' import { onCancel, ParamsError } from '../../../util/error' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'import' -export const desc = '匯入現有的 Quorum Network' +export const desc = '匯入現有的 Eth Network' interface OptType { interactive: boolean @@ -15,12 +16,21 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum backup import --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth backup import --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } export const handler = async (argv: Arguments) => { - const backup = new Backup(config) + 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 backup = new Backup(config, networkType) const archive: string = await (async () => { const archiveList = backup.getBackupItems() @@ -35,7 +45,7 @@ export const handler = async (argv: Arguments) => { throw new ParamsError('Invalid params: Required parameter missing') } })() - const spinner = ora('Quorum Network Import ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Import ...`).start() await backup.import(archive) - spinner.succeed('Quorum Network Import Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Import Successfully!`) } diff --git a/src/eth/command/cluster/apply.ts b/src/eth/command/cluster/apply.ts index 97870b7a..c3f7939d 100644 --- a/src/eth/command/cluster/apply.ts +++ b/src/eth/command/cluster/apply.ts @@ -25,7 +25,7 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const cluster = new Cluster(config) + const cluster = new Cluster(config, 'quorum') const wallet = new Wallet() const confirm: boolean = await (async () => { diff --git a/src/eth/command/cluster/delete.ts b/src/eth/command/cluster/delete.ts index ed3a448c..b61d6582 100644 --- a/src/eth/command/cluster/delete.ts +++ b/src/eth/command/cluster/delete.ts @@ -19,7 +19,7 @@ export const builder = (yargs: Argv) => { } export const handler = async () => { - const cluster = new Cluster(config) + const cluster = new Cluster(config, 'quorum') const confirm: boolean = await (async () => { const fileList = cluster.getHelmChartFiles() diff --git a/src/eth/command/cluster/generate.ts b/src/eth/command/cluster/generate.ts index e7423873..64598bb3 100644 --- a/src/eth/command/cluster/generate.ts +++ b/src/eth/command/cluster/generate.ts @@ -25,7 +25,7 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const cluster = new Cluster(config) + const cluster = new Cluster(config, 'quorum') const wallet = new Wallet() const confirm: boolean = await (async () => { diff --git a/src/eth/command/explorer/create.ts b/src/eth/command/explorer/create.ts index 18d4467d..569926f6 100644 --- a/src/eth/command/explorer/create.ts +++ b/src/eth/command/explorer/create.ts @@ -22,8 +22,8 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const explorer = new Explorer(config) - const backup = new Backup(config) + const explorer = new Explorer(config, 'quorum') + const backup = new Backup(config, 'quorum') const getBackupItems = backup.getExportItems() const explorerCreate: ExplorerCreateType = await (async () => { diff --git a/src/eth/command/explorer/delete.ts b/src/eth/command/explorer/delete.ts index a15c4bb6..82baa2e4 100644 --- a/src/eth/command/explorer/delete.ts +++ b/src/eth/command/explorer/delete.ts @@ -11,7 +11,7 @@ export const desc = '刪除現有的 Quorum Explorer.' export const builder = {} export const handler = async () => { - const explorer = new Explorer(config) + const explorer = new Explorer(config, 'quorum') let confirmDelete = true diff --git a/src/eth/command/network/add.ts b/src/eth/command/network/add.ts index 96841837..ebe506de 100644 --- a/src/eth/command/network/add.ts +++ b/src/eth/command/network/add.ts @@ -6,6 +6,7 @@ import { onCancel, ParamsError } from '../../../util/error' import ora from 'ora' import { AddValidatorRemoteType, AddMemberRemoteType } from '../../model/type/network.type' import { ethers } from 'ethers' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'add' @@ -22,7 +23,16 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const network = new Network(config) + 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 network = new Network(config, networkType) if (argv.interactive) { const connectOptionList = [ @@ -53,13 +63,13 @@ export const handler = async (argv: Arguments) => { if (connectOption === 'local') { if (nodeOption === 'validator') { - const spinner = ora('Quorum Network Add ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Add ...`).start() const validatorNum = await network.addValidatorLocal() - spinner.succeed(`Quorum Network Add Validator${validatorNum} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Add Validator${validatorNum} Successfully!`) } else { - const spinner = ora('Quorum Network Add ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Add ...`).start() const memberNum = await network.addMemberLocal() - spinner.succeed(`Quorum Network Add Member${memberNum} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Add Member${memberNum} Successfully!`) } } else if (connectOption === 'remote') { if (nodeOption === 'validator') { @@ -87,9 +97,9 @@ export const handler = async (argv: Arguments) => { ipAddress: ipAddress, } - const spinner = ora('Quorum Network Add ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Add ...`).start() await network.addValidatorRemote(addValidatorRemoteConfig) - spinner.succeed(`Quorum Network Add Validator ${validatorAddress} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Add Validator ${validatorAddress} Successfully!`) } else { const { enodeInfo, ipAddress } = await prompts([ { @@ -115,9 +125,9 @@ export const handler = async (argv: Arguments) => { ipAddress: ipAddress, } - const spinner = ora('Quorum Network Add ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Add ...`).start() await network.addMemberRemote(addMemberRemoteConfig) - spinner.succeed(`Quorum Network Add Member ${memberAddress} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Add Member ${memberAddress} Successfully!`) } // TODO: addMemberRemote } diff --git a/src/eth/command/network/check.ts b/src/eth/command/network/check.ts index 54a38eff..3a722e20 100644 --- a/src/eth/command/network/check.ts +++ b/src/eth/command/network/check.ts @@ -20,7 +20,7 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const network = new Network(config) + const network = new Network(config, 'quorum') if (argv.interactive) { const node: string = await (async () => { diff --git a/src/eth/command/network/create.ts b/src/eth/command/network/create.ts index 5b8d34c9..381a92ed 100644 --- a/src/eth/command/network/create.ts +++ b/src/eth/command/network/create.ts @@ -10,10 +10,10 @@ import { defaultNetworkConfig } from '../../model/defaultNetworkConfig' import ora from 'ora' import Wallet from '../../../wallet/service/wallet' import { WalletType } from '../../../wallet/model/type/wallet.type' - +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'create' -export const desc = '產生 Quorum Network 所需的相關設定檔案並建立網路' +export const desc = '產生 Eth Network 所需的相關設定檔案並建立網路' interface OptType { interactive: boolean @@ -21,13 +21,23 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network create --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network create --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } export const handler = async (argv: Arguments) => { - const network = new Network(config) - const backup = new Backup(config) + const { networkType } = await prompts([ + { + type: 'select', + name: 'networkType', + message: 'What is your network?', + choices: getNetworkTypeChoices(), + }, + ]) + + const network = new Network(config, networkType) + const networkTypeWithBigFirstLetter = networkType.charAt(0).toUpperCase() + networkType.slice(1) + const backup = new Backup(config, networkType) const wallet = new Wallet() // check bdkPath files exist or not (include useless file e.g. .DS_Store) const confirm: boolean = await (async () => { @@ -37,11 +47,11 @@ 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 ${networkType} nodes already exists. The following processes will remove all existing files. Continue?`, initial: false, }, { onCancel })).value if (confirmDelete) { - const spinner = ora('Quorum Network Create ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Create ...`).start() // backup before remove await backup.exportAll() @@ -168,14 +178,15 @@ export const handler = async (argv: Arguments) => { amount: '1000000000000000000000000000', }] - return { chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList } + return { networkType, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList } } else { const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM) return defaultNetworkConfig(address, privateKey) } - })() - const spinner = ora('Quorum Network Create ...').start() + } + )() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Create ...`).start() await network.create(networkCreate) - spinner.succeed('Quorum Network Create Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Create Successfully!`) } } diff --git a/src/eth/command/network/delete.ts b/src/eth/command/network/delete.ts index 8e546507..58075c6d 100644 --- a/src/eth/command/network/delete.ts +++ b/src/eth/command/network/delete.ts @@ -3,15 +3,24 @@ import Network from '../../service/network' 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 Network' - -export const builder = {} +export const desc = '刪除現有的 Eth Network' export const handler = async () => { - const network = new Network(config) + 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 network = new Network(config, networkType) let confirmDelete = true @@ -25,8 +34,8 @@ export const handler = async () => { confirmDelete = response.value if (confirmDelete) { - const spinner = ora('Quorum Network Delete ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Delete ...`).start() await network.delete() - spinner.succeed('Quorum Network Delete Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Delete Successfully!`) } } diff --git a/src/eth/command/network/down.ts b/src/eth/command/network/down.ts index a5540f80..90484e5c 100644 --- a/src/eth/command/network/down.ts +++ b/src/eth/command/network/down.ts @@ -4,32 +4,41 @@ import Network from '../../service/network' import { logger, onCancel } from '../../../util' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'down' -export const desc = '停止現有的 Quorum Network' +export const desc = '停止現有的 Eth Network' export const builder = {} export const handler = async (argv: Arguments) => { logger.debug('exec network down', argv.$0) - const network = new Network(config) + const { networkType } = await prompts([ + { + type: 'select', + name: 'networkType', + message: 'What is your network?', + choices: getNetworkTypeChoices(), + }, + ]) + const network = new Network(config, networkType) let confirmDelete = true const response = await prompts({ type: 'confirm', name: 'value', - message: 'Confirm to down Quorum Network?', + message: `Confirm to down ${networkType} Network?`, initial: false, }, { onCancel }) confirmDelete = response.value if (confirmDelete) { - const spinner = ora('Quorum Network Down ...').start() + const spinner = ora(`${networkType} Network Down ...`).start() await network.down() - spinner.succeed('Quorum Network Down Successfully!') + spinner.succeed(`${networkType} Network Down Successfully!`) } } diff --git a/src/eth/command/network/generate.ts b/src/eth/command/network/generate.ts index 4f003e66..fdac8b00 100644 --- a/src/eth/command/network/generate.ts +++ b/src/eth/command/network/generate.ts @@ -6,10 +6,11 @@ import { onCancel, ParamsError } from '../../../util/error' import { NetworkGenerateType } from '../../model/type/network.type' import config from '../../config' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'generate' -export const desc = '產生 Quorum Network 所需的相關設定檔案' +export const desc = '產生 Eth Network 所需的相關設定檔案' interface OptType { interactive: boolean @@ -17,13 +18,22 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum network generate --interactive', 'Cathay BDK 互動式問答') + .example('bdk eth network generate --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } export const handler = async (argv: Arguments) => { - const network = new Network(config) - const backup = new Backup(config) + 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 network = new Network(config, networkType) + const backup = new Backup(config, networkType) // check bdkPath files exist or not (include useless file e.g. .DS_Store) const confirm: boolean = await (async () => { network.createBdkFolder() @@ -36,7 +46,7 @@ export const handler = async (argv: Arguments) => { initial: false, }, { onCancel })).value if (confirmDelete) { - const spinner = ora('Quorum Network Create ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Create ...`).start() // backup before remove await backup.exportAll() @@ -79,8 +89,8 @@ export const handler = async (argv: Arguments) => { throw new ParamsError('Invalid params: You need to generate at least one node') } - const spinner = ora('Quorum Network Generate ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Generate ...`).start() await network.generate(networkGenerate) - spinner.succeed('Quorum Network Generate Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Generate Successfully!`) } } diff --git a/src/eth/command/network/get.ts b/src/eth/command/network/get.ts index 60a261f0..e6be8b05 100644 --- a/src/eth/command/network/get.ts +++ b/src/eth/command/network/get.ts @@ -4,6 +4,7 @@ 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 = 'get' @@ -20,7 +21,16 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const network = new Network(config) + 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 network = new Network(config, networkType) if (argv.interactive) { const getOption = [ @@ -53,10 +63,10 @@ export const handler = async (argv: Arguments) => { }, ], { onCancel }) - const spinner = ora('Quorum Network Get ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Get ...`).start() const result = await network.getNetworkInfo(networkInfo) - spinner.succeed(`Quorum Network Get Result: ${result}`) - spinner.succeed('Quorum Network Get Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Get Result: ${result}`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Get Successfully!`) } else if (get === 'node') { const node: string = await (async () => { const nodeList = network.getUpExportItems() @@ -88,10 +98,10 @@ export const handler = async (argv: Arguments) => { choices: nodeOption, }, ], { onCancel }) - const spinner = ora('Quorum Network Get ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Get ...`).start() const result = network.getNodeInfo(node, nodeInfo) - spinner.succeed(`Quorum Network Get Result: ${result}`) - spinner.succeed('Quorum Network Get Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Get Result: ${result}`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Get Successfully!`) } } else { throw new ParamsError('Invalid params: Required parameter missing') diff --git a/src/eth/command/network/join.ts b/src/eth/command/network/join.ts index 6dde1b0b..cc936d99 100644 --- a/src/eth/command/network/join.ts +++ b/src/eth/command/network/join.ts @@ -5,6 +5,7 @@ import Network from '../../service/network' import { onCancel, ParamsError, ProcessError } from '../../../util/error' import ora from 'ora' import { JoinNodeType } from '../../model/type/network.type' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'join' @@ -21,7 +22,16 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const network = new Network(config) + 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 network = new Network(config, networkType) if (argv.interactive) { const node: string = await (async () => { @@ -67,9 +77,9 @@ export const handler = async (argv: Arguments) => { staticNodesJson: JSON.parse(staticNodesJson), } - const spinner = ora('Quorum Network Join ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Join ...`).start() await network.joinNode(joinNodeConfig) - spinner.succeed(`Quorum Network Join ${node} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Join ${node} Successfully!`) } else { throw new ParamsError('Invalid params: Required parameter missing') } diff --git a/src/eth/command/network/up.ts b/src/eth/command/network/up.ts index 83d15485..0ab69ee9 100644 --- a/src/eth/command/network/up.ts +++ b/src/eth/command/network/up.ts @@ -4,6 +4,7 @@ import Network from '../../service/network' import { onCancel, ParamsError, ProcessError } from '../../../util/error' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' export const command = 'up' @@ -22,12 +23,21 @@ export const builder = (yargs: Argv) => { } export const handler = async (argv: Arguments) => { - const network = new Network(config) + 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 network = new Network(config, networkType) if (argv.all) { - const spinner = ora('Quorum Network Up All ...').start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Up All ...`).start() await network.upAll() - spinner.succeed('Quorum Network Up All Successfully!') + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Up All Successfully!`) } else if (argv.interactive) { const node: string = await (async () => { const nodeList = network.getUpExportItems() @@ -44,9 +54,9 @@ export const handler = async (argv: Arguments) => { } })() - const spinner = ora(`Quorum Network Up ${node} ...`).start() + const spinner = ora(`${networkTypeWithBigFirstLetter} Network Up ${node} ...`).start() await network.upService(node) - spinner.succeed(`Quorum Network Up ${node} Successfully!`) + spinner.succeed(`${networkTypeWithBigFirstLetter} Network Up ${node} Successfully!`) } else { throw new ParamsError('Invalid params: Required parameter missing') } diff --git a/src/eth/config.ts b/src/eth/config.ts index 3aa5ad67..e68920bf 100644 --- a/src/eth/config.ts +++ b/src/eth/config.ts @@ -41,7 +41,7 @@ const environment = (() => { })() const nodeType = (() => { - switch (process.env.BDK_QUORUM_NODE_TYPE) { + switch (process.env.BDK_ETH_NODE_TYPE) { case 'validator': return NodeTypeEnum.VALIDATOR default: @@ -62,7 +62,7 @@ const config: Config = { dockerHostPath: process.env.BDK_DOCKER_HOST_PATH || bdkPath, dockerPath: '/tmp', }, - networkName: process.env.BDK_ETH_NETWORK_NAME || 'bdk-quorum-network', + networkName: '', nodeType: nodeType, hostname: process.env.BDK_HOSTNAME || '', UID: process.env.UID === undefined ? os.userInfo().uid : parseInt(process.env.UID, 10), diff --git a/src/eth/config/besu/besuGenesisConfig.ts b/src/eth/config/besu/besuGenesisConfig.ts new file mode 100644 index 00000000..7f59409d --- /dev/null +++ b/src/eth/config/besu/besuGenesisConfig.ts @@ -0,0 +1,34 @@ +import { GenesisJsonType } from '../../model/type/network.type' + +const besuGenesisConfig: GenesisJsonType = { + nonce: '0x0', + timestamp: `0x${Math.floor(Date.now() / 1000).toString(16)}`, + extraData: '0x0', + gasLimit: '0xE0000000', + gasUsed: '0x0', + number: '0x0', + difficulty: '0x1', + coinbase: '0x0000000000000000000000000000000000000000', + mixHash: '0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365', + parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + config: { + chainId: 81712, + homesteadBlock: 0, + eip150Block: 0, + eip150Hash: '0x0000000000000000000000000000000000000000000000000000000000000000', + eip155Block: 0, + eip158Block: 0, + byzantiumBlock: 0, + constantinopleBlock: 0, + petersburgBlock: 0, + istanbulBlock: 0, + qbft: { + blockPeriodSeconds: 1, + epochLength: 30000, + requestTimeoutSeconds: 60, + }, + }, + alloc: {}, +} + +export default besuGenesisConfig diff --git a/src/eth/config/besu/besuMemberConfig.ts b/src/eth/config/besu/besuMemberConfig.ts new file mode 100644 index 00000000..d7efa56b --- /dev/null +++ b/src/eth/config/besu/besuMemberConfig.ts @@ -0,0 +1,29 @@ +import { NetworkConfigType, NetworkType } from '../network.type' + +const besuConfig: NetworkConfigType = { + image: 'hyperledger/besu:latest', + networks: [NetworkType.BESU], + entrypoint: (chainId, peerPort, bootnode, nodeEncode) => [ + '/bin/sh', '-c', + `besu --data-path=/data \ + --genesis-file=/data/genesis.json \ + --network-id=${chainId} \ + ${(bootnode) ? '--bootnodes '.concat(nodeEncode) : ''}\ + --logging=INFO \ + --sync-mode=FULL \ + --rpc-http-enabled \ + --rpc-http-port=8545 \ + --host-whitelist="*" \ + --rpc-http-api=ADMIN,DEBUG,EEA,ETH,MINER,NET,PERM,PLUGINS,PRIV,QBFT,TRACE,TXPOOL,WEB3 \ + --rpc-ws-enabled \ + --rpc-ws-port=8546 \ + --rpc-ws-api=ADMIN,DEBUG,EEA,ETH,MINER,NET,PERM,PLUGINS,PRIV,QBFT,TRACE,TXPOOL,WEB3 \ + --rpc-http-cors-origins="*" \ + --rpc-http-host="0.0.0.0" \ + --rpc-ws-host="0.0.0.0" \ + --Xdns-enabled=true \ + --p2p-port=${peerPort}`, + ], +} + +export default besuConfig diff --git a/src/eth/config/besu/besuValidatorConfig.ts b/src/eth/config/besu/besuValidatorConfig.ts new file mode 100644 index 00000000..e95e3307 --- /dev/null +++ b/src/eth/config/besu/besuValidatorConfig.ts @@ -0,0 +1,13 @@ +import { NetworkConfigType, NetworkType } from '../network.type' + +const besuConfig: NetworkConfigType = { + image: 'hyperledger/besu:latest', + networks: [NetworkType.BESU], + entrypoint: (chainId, peerPort, bootnode, nodeEncode) => [ + '/bin/sh', + '-c', + `besu --data-path=/data --genesis-file=/data/genesis.json --Xdns-enabled=true --network-id=${chainId} ${bootnode ? '--bootnodes '.concat(nodeEncode) : ''} --logging=INFO --graphql-http-enabled --sync-mode=FULL --rpc-http-enabled --rpc-http-port=8545 --host-whitelist="*" --rpc-http-api=EEA,WEB3,ETH,NET,TRACE,DEBUG,ADMIN,TXPOOL,QBFT --rpc-ws-enabled --rpc-ws-port=8546 --rpc-ws-api=EEA,WEB3,ETH,NET,TRACE,DEBUG,ADMIN,TXPOOL,QBFT --rpc-http-cors-origins="*" --rpc-http-host="0.0.0.0" --rpc-ws-host="0.0.0.0" --miner-enabled --miner-coinbase=0x0000000000000000000000000000000000000000 --min-gas-price=0 --p2p-port=${peerPort}`, + ], +} + +export default besuConfig diff --git a/src/eth/config/network.type.ts b/src/eth/config/network.type.ts new file mode 100644 index 00000000..ba9499a0 --- /dev/null +++ b/src/eth/config/network.type.ts @@ -0,0 +1,22 @@ +export enum NetworkType { + BESU = 'besu', + QUORUM = 'quorum', +} + +export interface NetworkConfigType { + image: string + networks: NetworkType[] + entrypoint: ( + chainId: number, + peerPort: number, + bootnode: boolean, + nodeEncode: string + ) => string[] +} + +export const getNetworkTypeChoices = () => { + return Object.values(NetworkType).map(value => ({ + title: value.charAt(0).toUpperCase() + value.slice(1), + value: value, + })) +} diff --git a/src/eth/config/networkConfigLoader.ts b/src/eth/config/networkConfigLoader.ts new file mode 100644 index 00000000..808ef8e1 --- /dev/null +++ b/src/eth/config/networkConfigLoader.ts @@ -0,0 +1,47 @@ +import { GenesisJsonType } from '../model/type/network.type' +import { NetworkConfigType, NetworkType } from './network.type' +import besuMemberConfig from './besu/besuMemberConfig' +import besuValidatorConfig from './besu/besuValidatorConfig' +import quorumMemberConfig from './quorum/quorumMemberConfig' +import quorumValidatorConfig from './quorum/quorumValidatorConfig' +import quorumGenesisConfig from './quorum/quorumGenesisConfig' +import besuGenesisConfig from './besu/besuGenesisConfig' +import { NodeTypeEnum } from '../model/type/config.type' + +const networkConfigs: { [key in NetworkType]: { member: NetworkConfigType; validator: NetworkConfigType; genesisJson: GenesisJsonType, ethereumJsonRpcVariant: String } } = { + [NetworkType.BESU]: { + member: besuMemberConfig, + validator: besuValidatorConfig, + genesisJson: besuGenesisConfig, + ethereumJsonRpcVariant: 'besu', + }, + [NetworkType.QUORUM]: { + member: quorumMemberConfig, + validator: quorumValidatorConfig, + genesisJson: quorumGenesisConfig, + ethereumJsonRpcVariant: 'geth', + }, +} + +export const getNetworkConfig = (networkType: NetworkType, nodeType: NodeTypeEnum): NetworkConfigType => { + const config = networkConfigs[networkType][nodeType] + if (!config) { + throw new Error(`Unsupported network type: ${networkType}`) + } + return config +} + +export const getGenesisJson = (networkType: NetworkType): GenesisJsonType => { + const genesisJson = networkConfigs[networkType].genesisJson + if (!genesisJson) { + throw new Error(`Unsupported network type: ${networkType}`) + } + return genesisJson +} +export const getEthereumJsonRpcVariant = (networkType: NetworkType): String => { + const ethereumJsonRpcVariant = networkConfigs[networkType].ethereumJsonRpcVariant + if (!ethereumJsonRpcVariant) { + throw new Error(`Unsupported network type: ${networkType}`) + } + return ethereumJsonRpcVariant +} diff --git a/src/eth/config/quorum/quorumGenesisConfig.ts b/src/eth/config/quorum/quorumGenesisConfig.ts new file mode 100644 index 00000000..804280ec --- /dev/null +++ b/src/eth/config/quorum/quorumGenesisConfig.ts @@ -0,0 +1,46 @@ +import { GenesisJsonType } from '../../model/type/network.type' + +const quorumGenesisConfig: GenesisJsonType = { + nonce: '0x0', + timestamp: `0x${Math.floor(Date.now() / 1000).toString(16)}`, + extraData: '0x0', + gasLimit: '0xE0000000', + gasUsed: '0x0', + number: '0x0', + difficulty: '0x1', + coinbase: '0x0000000000000000000000000000000000000000', + mixHash: '0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365', + parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + config: { + chainId: 81712, + homesteadBlock: 0, + eip150Block: 0, + eip150Hash: '0x0000000000000000000000000000000000000000000000000000000000000000', + eip155Block: 0, + eip158Block: 0, + byzantiumBlock: 0, + constantinopleBlock: 0, + petersburgBlock: 0, + istanbulBlock: 0, + qbft: { + epochLength: 30000, + blockPeriodSeconds: 1, + emptyBlockPeriodSeconds: 3600, + requestTimeoutSeconds: 60, + policy: 0, + ceil2Nby3Block: 0, + }, + transitions: [ + { + block: 0, + transactionSizeLimit: 64, + contractSizeLimit: 64, + }, + ], + txnSizeLimit: 64, + isQuorum: true, + }, + alloc: {}, +} + +export default quorumGenesisConfig diff --git a/src/eth/config/quorum/quorumMemberConfig.ts b/src/eth/config/quorum/quorumMemberConfig.ts new file mode 100644 index 00000000..7886f95b --- /dev/null +++ b/src/eth/config/quorum/quorumMemberConfig.ts @@ -0,0 +1,13 @@ +import { NetworkConfigType, NetworkType } from '../network.type' + +const quorumConfig: NetworkConfigType = { + image: 'quorumengineering/quorum:23.4.0', + networks: [NetworkType.QUORUM], + entrypoint: (chainId, peerPort, bootnode, nodeEncode) => [ + '/bin/sh', + '-c', + `geth init --datadir /data /data/genesis.json; geth --datadir /data --networkid ${chainId} ${(bootnode) ? '--bootnodes '.concat(nodeEncode) : '--nodiscover'} --verbosity 3 --syncmode full --nousb --http --http.addr 0.0.0.0 --http.port 8545 --http.corsdomain "*" --http.vhosts "*" --ws --ws.addr 0.0.0.0 --ws.port 8546 --ws.origins "*" --http.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --ws.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --port ${peerPort}`, + ], +} + +export default quorumConfig diff --git a/src/eth/config/quorum/quorumValidatorConfig.ts b/src/eth/config/quorum/quorumValidatorConfig.ts new file mode 100644 index 00000000..5fc015e4 --- /dev/null +++ b/src/eth/config/quorum/quorumValidatorConfig.ts @@ -0,0 +1,13 @@ +import { NetworkConfigType, NetworkType } from '../network.type' + +const quorumConfig: NetworkConfigType = { + image: 'quorumengineering/quorum:23.4.0', + networks: [NetworkType.QUORUM], + entrypoint: (chainId, peerPort, bootnode, nodeEncode) => [ + '/bin/sh', + '-c', + `geth init --datadir /data /data/genesis.json; geth --datadir /data --networkid=${chainId} --verbosity 3 --syncmode full --nousb --mine --miner.threads 1 --miner.gasprice 0 --emitcheckpoints --http --http.addr 0.0.0.0 --http.port=8545 --http.corsdomain="*" ${bootnode ? '--bootnodes '.concat(nodeEncode) : '--nodiscover'} --http.vhosts="*" --ws --ws.addr=0.0.0.0 --ws.port=8546 --ws.origins="*" --http.api=admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --ws.api=admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --port=${peerPort}`, + ], +} + +export default quorumConfig diff --git a/src/eth/model/type/network.type.ts b/src/eth/model/type/network.type.ts index d5c9213c..5baf2ffc 100644 --- a/src/eth/model/type/network.type.ts +++ b/src/eth/model/type/network.type.ts @@ -14,6 +14,8 @@ export interface AllocType { * @requires alloc - [{@link AllocType} array] 原生代幣分配設定 */ export interface NetworkCreateType { + //TODO - networkType?: ? should be removed, after cluster is integrated + networkType?: string chainId: number validatorNumber: number memberNumber: number @@ -58,20 +60,20 @@ export interface GenesisJsonType { qbft: { epochLength: number blockPeriodSeconds: number - emptyBlockPeriodSeconds: number + emptyBlockPeriodSeconds?: number requestTimeoutSeconds: number - policy: number - ceil2Nby3Block: number + policy?: number + ceil2Nby3Block?: number } - transitions: { + transitions?: { block?: number transactionSizeLimit?: number contractSizeLimit?: number blockPeriodSeconds?: number emptyBlockPeriodSeconds?: number }[] - txnSizeLimit: number - isQuorum: boolean + txnSizeLimit?: number + isQuorum?: boolean } alloc: { [key: string]: Alloc diff --git a/src/eth/model/yaml/docker-compose/memberDockerCompose.ts b/src/eth/model/yaml/docker-compose/memberDockerCompose.ts index 68f4104f..2195a138 100644 --- a/src/eth/model/yaml/docker-compose/memberDockerCompose.ts +++ b/src/eth/model/yaml/docker-compose/memberDockerCompose.ts @@ -1,10 +1,26 @@ import DockerComposeYaml from './dockerComposeYaml' - +import { getNetworkConfig } from '../../../config/networkConfigLoader' +import { NetworkType } from '../../../config/network.type' +import { NodeTypeEnum } from '../../type/config.type' class MemberDockerComposeYaml extends DockerComposeYaml { - public addMember (bdkPath: string, memberNum: number, rpcPort: number, chainId: number, peerPort: number, bootnode: boolean, nodeEncode: string) { - this.addNetwork('quorum', {}) + public addMember ( + bdkPath: string, + memberNum: number, + rpcPort: number, + chainId: number, + peerPort: number, + bootnode: boolean, + nodeEncode: string, + networkType: NetworkType, + ) { + const config = getNetworkConfig(networkType, NodeTypeEnum.MEMBER) + if (!config) { + throw new Error(`Unsupported network type: ${networkType}`) + } + + this.addNetwork(networkType, {}) this.addService(`member${memberNum}`, { - image: 'quorumengineering/quorum:23.4.0', + image: config.image, // eslint-disable-next-line no-template-curly-in-string user: '${UID}:${GID}', container_name: `member${memberNum}`, @@ -16,12 +32,9 @@ class MemberDockerComposeYaml extends DockerComposeYaml { `${peerPort}:${peerPort}/tcp`, `${peerPort}:${peerPort}/udp`, ], - networks: ['quorum'], + networks: config.networks, volumes: [`${bdkPath}/member${memberNum}/data/:/data`], - entrypoint: [ - '/bin/sh', '-c', - `geth init --datadir /data /data/genesis.json; geth --datadir /data --networkid ${chainId} ${(bootnode) ? '--bootnodes '.concat(nodeEncode) : '--nodiscover'} --verbosity 3 --syncmode full --nousb --http --http.addr 0.0.0.0 --http.port 8545 --http.corsdomain "*" --http.vhosts "*" --ws --ws.addr 0.0.0.0 --ws.port 8546 --ws.origins "*" --http.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --ws.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --port ${peerPort}`, - ], + entrypoint: config.entrypoint(chainId, peerPort, bootnode, nodeEncode), }) } } diff --git a/src/eth/model/yaml/docker-compose/validatorDockerComposeYaml.ts b/src/eth/model/yaml/docker-compose/validatorDockerComposeYaml.ts index 20fc2257..19eb1d74 100644 --- a/src/eth/model/yaml/docker-compose/validatorDockerComposeYaml.ts +++ b/src/eth/model/yaml/docker-compose/validatorDockerComposeYaml.ts @@ -1,10 +1,27 @@ import DockerComposeYaml from './dockerComposeYaml' +import { getNetworkConfig } from '../../../config/networkConfigLoader' +import { NetworkType } from '../../../config/network.type' +import { NodeTypeEnum } from '../../type/config.type' class ValidatorDockerComposeYaml extends DockerComposeYaml { - public addValidator (bdkPath: string, validatorNum: number, rpcPort: number, chainId: number, peerPort: number, bootnode: boolean, nodeEncode: string) { - this.addNetwork('quorum', {}) + public addValidator ( + bdkPath: string, + validatorNum: number, + rpcPort: number, + chainId: number, + peerPort: number, + bootnode: boolean, + nodeEncode: string, + networkType: NetworkType, + ) { + const config = getNetworkConfig(networkType, NodeTypeEnum.VALIDATOR) + if (!config) { + throw new Error(`Unsupported network type: ${networkType}`) + } + + this.addNetwork(networkType, {}) this.addService(`validator${validatorNum}`, { - image: 'quorumengineering/quorum:23.4.0', + image: config.image, // eslint-disable-next-line no-template-curly-in-string user: '${UID}:${GID}', container_name: `validator${validatorNum}`, @@ -16,12 +33,9 @@ class ValidatorDockerComposeYaml extends DockerComposeYaml { `${peerPort}:${peerPort}/tcp`, `${peerPort}:${peerPort}/udp`, ], - networks: ['quorum'], + networks: config.networks, volumes: [`${bdkPath}/validator${validatorNum}/data/:/data`], - entrypoint: [ - '/bin/sh', '-c', - `geth init --datadir /data /data/genesis.json; geth --datadir /data --networkid ${chainId} --verbosity 3 --syncmode full --nousb --mine --miner.threads 1 --miner.gasprice 0 --emitcheckpoints --http --http.addr 0.0.0.0 --http.port 8545 --http.corsdomain "*" ${(bootnode) ? '--bootnodes '.concat(nodeEncode) : '--nodiscover'} --http.vhosts "*" --ws --ws.addr 0.0.0.0 --ws.port 8546 --ws.origins "*" --http.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --ws.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft --port ${peerPort} `, - ], + entrypoint: config.entrypoint(chainId, peerPort, bootnode, nodeEncode), }) } } diff --git a/src/eth/model/yaml/network/gensisJson.ts b/src/eth/model/yaml/network/gensisJson.ts index e7e1ba9e..be1a9a40 100644 --- a/src/eth/model/yaml/network/gensisJson.ts +++ b/src/eth/model/yaml/network/gensisJson.ts @@ -1,51 +1,12 @@ import BdkYaml from '../bdkYaml' import { GenesisJsonType } from '../../type/network.type' - +import { NetworkType } from '../../../config/network.type' +import { getGenesisJson } from '../../../config/networkConfigLoader' class GenesisJsonYaml extends BdkYaml { - constructor (value?: GenesisJsonType) { - // dafault value in quorum node genesis.json - super(value || { - nonce: '0x0', - timestamp: `0x${Math.floor(Date.now() / 1000).toString(16)}`, - extraData: '0x0', - gasLimit: '0xE0000000', - gasUsed: '0x0', - number: '0x0', - difficulty: '0x1', - coinbase: '0x0000000000000000000000000000000000000000', - mixHash: '0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365', - parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', - config: { - chainId: 81712, - homesteadBlock: 0, - eip150Block: 0, - eip150Hash: '0x0000000000000000000000000000000000000000000000000000000000000000', - eip155Block: 0, - eip158Block: 0, - byzantiumBlock: 0, - constantinopleBlock: 0, - petersburgBlock: 0, - istanbulBlock: 0, - qbft: { - epochLength: 30000, - blockPeriodSeconds: 1, - emptyBlockPeriodSeconds: 3600, - requestTimeoutSeconds: 60, - policy: 0, - ceil2Nby3Block: 0, - }, - transitions: [ - { - block: 0, - transactionSizeLimit: 64, - contractSizeLimit: 64, - }, - ], - txnSizeLimit: 64, - isQuorum: true, - }, - alloc: {}, - }) + constructor (type: NetworkType, value?: GenesisJsonType) { + // Default values for quorum and besu nodes + + super(value || getGenesisJson(type)) } public addExtraData (extraData: string) { diff --git a/src/eth/service/Service.abstract.ts b/src/eth/service/Service.abstract.ts index a7c82aa5..5c655940 100644 --- a/src/eth/service/Service.abstract.ts +++ b/src/eth/service/Service.abstract.ts @@ -19,11 +19,15 @@ export abstract class AbstractService { constructor ( config: Config, + networkType: string, infra?: InfraRunner, kubernetesInfra?: KubernetesInfraRunner, ) { - this.config = config - this.bdkFile = new BdkFile(config) + this.config = { + ...config, + networkName: `bdk-${networkType}-network`, + } + this.bdkFile = new BdkFile(this.config) if (infra === undefined) { this.infra = InfraStrategy.createDockerRunner(new DockerRunner()) diff --git a/src/eth/service/backup.ts b/src/eth/service/backup.ts index e60ee833..dcf832b6 100644 --- a/src/eth/service/backup.ts +++ b/src/eth/service/backup.ts @@ -5,7 +5,7 @@ import { BackupError, tarDateFormat } from '../../util' export default class Backup extends AbstractService { /** - * @description 匯出 quorum network 備份資料 + * @description 匯出 eth network 備份資料 */ public exportAll () { const bdkPath = this.bdkFile.getBdkPath() @@ -24,7 +24,7 @@ export default class Backup extends AbstractService { } /** - * @description 匯出 quorum network 單一 node 備份資料 + * @description 匯出 eth network 單一 node 備份資料 */ public export (nodeName: string) { const bdkPath = this.bdkFile.getBdkPath() @@ -67,7 +67,7 @@ export default class Backup extends AbstractService { } /** - * @description 匯入 quorum network 備份資料 + * @description 匯入 eth network 備份資料 */ public import (tarFileName: string) { const bdkPath = this.bdkFile.getBdkPath() diff --git a/src/eth/service/network.ts b/src/eth/service/network.ts index 5c2976c0..0bd1f0f5 100644 --- a/src/eth/service/network.ts +++ b/src/eth/service/network.ts @@ -10,10 +10,11 @@ import MemberInstance from '../instance/member' import { DockerResultType } from '../instance/infra/InfraRunner.interface' import { TimeLimitError } from '../../util/error' import { sleep } from '../../util/utils' +import { NetworkType } from '../config/network.type' export default class Network extends AbstractService { /** - * @description 建立 quorum network + * @description 建立 eth network */ public async create (networkCreateConfig: NetworkCreateType) { const validatorAddressList: Buffer[] = [] @@ -35,7 +36,8 @@ export default class Network extends AbstractService { alloc[`0x${x.account.replace(/^0x/, '').toLowerCase()}`] = { balance: x.amount } }) - const genesisJsonYaml = new GenesisJsonYaml() + const networkType = (networkCreateConfig.networkType || 'quorum') as NetworkType + const genesisJsonYaml = new GenesisJsonYaml(networkType) genesisJsonYaml.addExtraData(extraData) genesisJsonYaml.addChainId(networkCreateConfig.chainId) genesisJsonYaml.addAlloc(alloc) @@ -72,8 +74,8 @@ export default class Network extends AbstractService { this.bdkFile.copyPrivateKeyToValidator(i) this.bdkFile.copyPublicKeyToValidator(i) this.bdkFile.copyAddressToValidator(i) - - validatorDockerComposeYaml.addValidator(bdkPath, i, 8545 + i * 2, networkCreateConfig.chainId, 30303 + i, networkCreateConfig.bootNodeList[i], staticNodesJson[i]) + + validatorDockerComposeYaml.addValidator(bdkPath, i, 8545 + i * 2, networkCreateConfig.chainId, 30303 + i, networkCreateConfig.bootNodeList[i], staticNodesJson[i], networkType) this.createNetworkInfoJson(networkInfo, `http://validator${i}:${8545 + i * 2}`) } this.bdkFile.createValidatorDockerComposeYaml(validatorDockerComposeYaml) @@ -92,7 +94,7 @@ export default class Network extends AbstractService { this.bdkFile.copyPublicKeyToMember(i) this.bdkFile.copyAddressToMember(i) - memberDockerComposeYaml.addMember(bdkPath, i, 8645 + i * 2, networkCreateConfig.chainId, 30403 + i, networkCreateConfig.bootNodeList[networkCreateConfig.validatorNumber + i], staticNodesJson[networkCreateConfig.validatorNumber + i]) + memberDockerComposeYaml.addMember(bdkPath, i, 8645 + i * 2, networkCreateConfig.chainId, 30403 + i, networkCreateConfig.bootNodeList[networkCreateConfig.validatorNumber + i], staticNodesJson[networkCreateConfig.validatorNumber + i], networkType) this.createNetworkInfoJson(networkInfo, `http://member${i}:${8645 + i * 2}`) } this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml) @@ -132,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, '') + validatorDockerComposeYaml.addValidator(bdkPath, nodeNum, 8545 + nodeNum * 2, joinNodeConfig.genesisJson.config.chainId, 30303 + nodeNum, false, '', NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://validator${nodeNum}:${8545 + nodeNum * 2}`) this.bdkFile.createValidatorDockerComposeYaml(validatorDockerComposeYaml) @@ -149,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, '') + memberDockerComposeYaml.addMember(bdkPath, nodeNum, 8645 + nodeNum * 2, joinNodeConfig.genesisJson.config.chainId, 30403 + nodeNum, false, '', NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://member${nodeNum}:${8645 + nodeNum * 2}`) this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml) @@ -285,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, '') + validatorDockerComposeYaml.addValidator(this.bdkFile.getBdkPath(), i, 8545 + i * 2, chainId, 30303 + i, false, '', NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://validator${i}:${8545 + i * 2}`) } this.bdkFile.createValidatorDockerComposeYaml(validatorDockerComposeYaml) @@ -339,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, '') + memberDockerComposeYaml.addMember(this.bdkFile.getBdkPath(), i, 8645 + i * 2, chainId, 30403 + i, false, '', NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://member${i}:${8645 + i * 2}`) } this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml) diff --git a/test/eth/service/backup.test.ts b/test/eth/service/backup.test.ts index 509c2937..4cdb4b2c 100644 --- a/test/eth/service/backup.test.ts +++ b/test/eth/service/backup.test.ts @@ -14,8 +14,8 @@ import { NetworkCreateType } from '../../../src/eth/model/type/network.type' describe('Quorum.Backup', function () { this.timeout(100000) - const backup = new Backup(config) - const network = new Network(config) + const backup = new Backup(config, 'quorum') + const network = new Network(config, 'quorum') const bdkPath = 'test/bdk' before(async function () { diff --git a/test/eth/service/explorer.test.ts b/test/eth/service/explorer.test.ts index 1447b53f..f1141cbe 100644 --- a/test/eth/service/explorer.test.ts +++ b/test/eth/service/explorer.test.ts @@ -11,8 +11,8 @@ describe('Quorum.Explorer.Service', function () { const docker: Dockerode = new Dockerode({ socketPath: '/var/run/docker.sock' }) const dockerdOption = { all: true } - const network = new Network(config) - const explorer = new Explorer(config) + const network = new Network(config, 'quorum') + const explorer = new Explorer(config, 'quorum') const explorerCreateOptions: ExplorerCreateType = { httpModeEnabled: false, nodeName: 'validator0', diff --git a/test/eth/service/network.test.ts b/test/eth/service/network.test.ts index 0cd7e24c..831c34a5 100644 --- a/test/eth/service/network.test.ts +++ b/test/eth/service/network.test.ts @@ -19,7 +19,7 @@ describe.skip('Quorum.Network.Service', function () { const bdkPath = 'test/bdk' const filePath = resolve(`${bdkPath}/bdk-quorum-network`) - const network = new Network(config) + const network = new Network(config, 'quorum') const wallet = new Wallet() const { address } = wallet.createWalletAddress(WalletType.ETHEREUM) const networkCreateConfig = { From a35f528b0cb9478f5f35fb635c346f817e933668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AC=9D=E6=98=8E=E8=8F=AF?= Date: Wed, 28 Aug 2024 14:11:37 +0800 Subject: [PATCH 4/6] feat: add network type support to replace Quorum-specific logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces a 'networkType' parameter to support different blockchain networks beyond Quorum. Key changes include: - Update cluster service and related commands to handle network type - Modify Kubernetes types and Helm Chart YAML models to accommodate network-specific configurations - Refactor BDK file processing to consider network type - Implement conditional logic in Genesis, Member, and Validator YAML generation based on network type ” ” --- src/eth/command/cluster/apply.ts | 30 ++++++--- src/eth/command/cluster/generate.ts | 28 +++++--- src/eth/instance/bdkFile.ts | 9 +++ src/eth/model/type/kubernetes.type.ts | 3 + src/eth/model/yaml/helm-chart/genesisYaml.ts | 40 ++++++++++- .../model/yaml/helm-chart/helmChartYaml.ts | 44 ++++++++++-- src/eth/model/yaml/helm-chart/memberYaml.ts | 41 +++++++++++- .../model/yaml/helm-chart/validatorYaml.ts | 39 ++++++++++- src/eth/service/cluster.ts | 67 ++++++++++++------- 9 files changed, 248 insertions(+), 53 deletions(-) diff --git a/src/eth/command/cluster/apply.ts b/src/eth/command/cluster/apply.ts index c3f7939d..6266ba86 100644 --- a/src/eth/command/cluster/apply.ts +++ b/src/eth/command/cluster/apply.ts @@ -9,10 +9,12 @@ import { WalletType } from '../../../wallet/model/type/wallet.type' import { defaultNetworkConfig } from '../../model/defaultNetworkConfig' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' +import { NetworkType } from '../../config/network.type' export const command = 'apply' -export const desc = '產生 Quorum Cluster 所需的相關設定檔案並建立網路' +export const desc = '產生 Network Cluster 所需的相關設定檔案並建立網路' interface OptType { interactive: boolean @@ -23,9 +25,17 @@ export const builder = (yargs: Argv) => { .example('bdk quorum cluster apply --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } - export const handler = async (argv: Arguments) => { - 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 cluster = new Cluster(config, networkType) const wallet = new Wallet() const confirm: boolean = await (async () => { @@ -34,13 +44,13 @@ export const handler = async (argv: Arguments) => { 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 ${networkType} 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() + const spinner = ora(`${networkType} Cluster Delete ...`).start() cluster.removeHelmChartFiles() - spinner.succeed('Remove all existing files!') + spinner.succeed(`Remove all existing files!`) } return confirmDelete } else { @@ -157,15 +167,15 @@ export const handler = async (argv: Arguments) => { const isBootNode = false const bootNodeList: boolean[] = Array(validatorNumber + memberNumber).fill(false) - return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList } + return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList, networkType } } else { const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM) const config = defaultNetworkConfig(address, privateKey) - return { ...config, provider: 'local' } + return { ...config, provider: 'local', networkType } } })() - const spinner = ora('Quorum Cluster Apply ...').start() + const spinner = ora(`${networkType} Cluster Apply ...`).start() await cluster.apply(clusterCreate, spinner) - spinner.succeed('Quorum Cluster Apply Successfully!') + spinner.succeed(`${networkType} Cluster Apply Successfully!`) } } diff --git a/src/eth/command/cluster/generate.ts b/src/eth/command/cluster/generate.ts index 64598bb3..f0665bca 100644 --- a/src/eth/command/cluster/generate.ts +++ b/src/eth/command/cluster/generate.ts @@ -9,10 +9,12 @@ import { defaultNetworkConfig } from '../../model/defaultNetworkConfig' import { onCancel } from '../../../util/error' import prompts from 'prompts' import ora from 'ora' +import { getNetworkTypeChoices } from '../../config/network.type' +import { NetworkType } from '../../config/network.type' export const command = 'generate' -export const desc = '產生 Quorum Cluster 所需的相關設定檔案' +export const desc = '產生 Network Cluster 所需的相關設定檔案' interface OptType { interactive: boolean @@ -20,12 +22,20 @@ interface OptType { export const builder = (yargs: Argv) => { return yargs - .example('bdk quorum cluster generate --interactive', 'Cathay BDK 互動式問答') + .example('bdk network cluster generate --interactive', 'Cathay BDK 互動式問答') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) } export const handler = async (argv: Arguments) => { - 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 cluster = new Cluster(config, networkType) const wallet = new Wallet() const confirm: boolean = await (async () => { @@ -34,11 +44,11 @@ export const handler = async (argv: Arguments) => { 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 ${networkType} 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() + const spinner = ora(`${networkType} Cluster Delete ...`).start() cluster.removeHelmChartFiles() spinner.succeed('Remove all existing files!') } @@ -183,16 +193,16 @@ export const handler = async (argv: Arguments) => { const isBootNode = false const bootNodeList: boolean[] = Array(validatorNumber + memberNumber).fill(false) - return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList } + return { provider, region, chainId, validatorNumber, memberNumber, alloc, isBootNode, bootNodeList, networkType } } else { const { address, privateKey } = wallet.createWalletAddress(WalletType.ETHEREUM) const config = defaultNetworkConfig(address, privateKey) - return { ...config, provider: 'local' } + return { ...config, provider: 'local', networkType } } })() - const spinner = ora('Quorum Cluster Generate ...').start() + const spinner = ora(`${networkType} Cluster Generate ...`).start() await cluster.generate(clusterGenerate, networkCreate) - spinner.succeed('Quorum Cluster Generate Successfully!') + spinner.succeed(`${networkType} Cluster Generate Successfully!`) } } diff --git a/src/eth/instance/bdkFile.ts b/src/eth/instance/bdkFile.ts index 030f59b0..99fa02cc 100644 --- a/src/eth/instance/bdkFile.ts +++ b/src/eth/instance/bdkFile.ts @@ -288,12 +288,21 @@ export default class BdkFile { this.checkHelmChartPath() return `${this.helmPath}/goquorum-genesis` } + public getBesuGenesisChartPath (): string { + this.checkHelmChartPath() + return `${this.helmPath}/besu-genesis` + } public getGoQuorumNodeChartPath (): string { this.checkHelmChartPath() return `${this.helmPath}/goquorum-node` } + public getBesuNodeChartPath (): string { + this.checkHelmChartPath() + return `${this.helmPath}/besu-node` + } + public createChartValueFolder () { fs.mkdirSync(`${this.helmPath}/values`, { recursive: true }) } diff --git a/src/eth/model/type/kubernetes.type.ts b/src/eth/model/type/kubernetes.type.ts index 33a04784..22d04f27 100644 --- a/src/eth/model/type/kubernetes.type.ts +++ b/src/eth/model/type/kubernetes.type.ts @@ -1,4 +1,6 @@ import { NetworkCreateType } from './network.type' +import { NetworkType } from '../../config/network.type' + export interface K8SRunCommandType { helmChart: string name: string @@ -13,6 +15,7 @@ export interface ClusterDeleteType { namespace: string } export interface ClusterCreateType extends NetworkCreateType { + networkType: NetworkType provider: string region?: string } diff --git a/src/eth/model/yaml/helm-chart/genesisYaml.ts b/src/eth/model/yaml/helm-chart/genesisYaml.ts index f2d46618..2a9555c1 100644 --- a/src/eth/model/yaml/helm-chart/genesisYaml.ts +++ b/src/eth/model/yaml/helm-chart/genesisYaml.ts @@ -1,7 +1,18 @@ import HelmChartYaml from './helmChartYaml' +import { NetworkType } from '../../../config/network.type' class GenesisConfigYaml extends HelmChartYaml { - public setGenesis (chainID: number, nodeCount: number) { + public setGenesis(networkType: NetworkType, chainID: number, nodeCount: number) { + if (networkType === 'quorum') { + this.setQuorumGenesis(chainID, nodeCount) + } else if (networkType === 'besu') { + this.setBesuGenesis(chainID, nodeCount) + } else { + throw new Error(`Unsupported network type: ${networkType}`) + } + } + + private setQuorumGenesis(chainID: number, nodeCount: number) { this.setQuorumFlags({ privacy: false, removeKeysOnDelete: false, @@ -36,6 +47,33 @@ class GenesisConfigYaml extends HelmChartYaml { } this.setService('rawGenesisConfig', genesisConfig) } + + private setBesuGenesis(chainID: number, nodeCount: number) { + const genesisConfig = { + genesis: { + config: { + chainId: chainID, + algorithm: { + consensus: 'qbft', + blockperiodseconds: 10, + epochlength: 30000, + requesttimeoutseconds: 20, + }, + }, + gasLimit: '0xf7b760', + difficulty: '0x1', + coinbase: '0x0000000000000000000000000000000000000000', + }, + blockchain: { + nodes: { + generate: true, + count: nodeCount, + }, + accountPassword: 'password', + }, + } + this.setService('rawGenesisConfig', genesisConfig) + } } export default GenesisConfigYaml diff --git a/src/eth/model/yaml/helm-chart/helmChartYaml.ts b/src/eth/model/yaml/helm-chart/helmChartYaml.ts index 1d73b8cc..c6ce439d 100644 --- a/src/eth/model/yaml/helm-chart/helmChartYaml.ts +++ b/src/eth/model/yaml/helm-chart/helmChartYaml.ts @@ -13,6 +13,13 @@ interface quorumFlags { usesBootnodes: boolean } +interface besuFlags { + privacy: boolean + removeKeysOnDelete: boolean + isBootnode: boolean + usesBootnodes: boolean +} + interface AwsInterface { serviceAccountName: string region: string @@ -26,7 +33,7 @@ interface AzureInterface { subscriptionId: string } -interface NodeInterface { +interface QuorumNodeInterface { goquorum: { metrics: { serviceMonitorEnabled: boolean @@ -45,12 +52,32 @@ interface NodeInterface { password: string } } +interface BesuNodeInterface { + besu: { + metrics: { + serviceMonitorEnabled: boolean + } + resources: { + cpuLimit: number + cpuRequest: number + memLimit: string + memRequest: string + } + account?: { + password: string + } + } + tessera?: { + password: string + } +} export interface HelmChartYamlInterface { quorumFlags: quorumFlags cluster?: ClusterInterface aws?: AwsInterface azure?: AzureInterface - node?: NodeInterface + quorumNode?: QuorumNodeInterface + besuNode?: BesuNodeInterface [key: string]: any } @@ -92,13 +119,22 @@ class HelmChartYaml extends BdkYaml { protected setQuorumFlags (quorumFlags: quorumFlags) { this.value.quorumFlags = quorumFlags } + protected setBesuFlags (besuFlags: besuFlags) { + this.value.besuFlags = besuFlags + } + + protected setCluster (cluster: ClusterInterface) { this.value.cluster = cluster } - protected setNode (node: NodeInterface) { - this.value.node = node + protected setQuorumNode (node: QuorumNodeInterface) { + this.value.quorumNode = node + } + + protected setBesuNode (besu: BesuNodeInterface) { + this.value.besuNode = besu } protected setService (name: string, service: any) { diff --git a/src/eth/model/yaml/helm-chart/memberYaml.ts b/src/eth/model/yaml/helm-chart/memberYaml.ts index 094fa4e2..42074d59 100644 --- a/src/eth/model/yaml/helm-chart/memberYaml.ts +++ b/src/eth/model/yaml/helm-chart/memberYaml.ts @@ -1,7 +1,18 @@ import HelmChartYaml from './helmChartYaml' +import { NetworkType } from '../../../config/network.type' class MemberConfigYaml extends HelmChartYaml { - public setQuorumConfigs (metrics = false) { + public setMember(networkType: NetworkType, metrics = false) { + if (networkType === 'quorum') { + this.setQuorumConfigs(metrics) + } else if (networkType === 'besu') { + this.setBesuConfigs(metrics) + } else { + throw new Error(`Unsupported network type: ${networkType}`) + } + } + + private setQuorumConfigs (metrics = false) { this.setQuorumFlags({ privacy: false, removeKeysOnDelete: false, @@ -9,7 +20,7 @@ class MemberConfigYaml extends HelmChartYaml { usesBootnodes: false, }) - this.setNode({ + this.setQuorumNode({ goquorum: { metrics: { // default value in helm is true @@ -27,6 +38,32 @@ class MemberConfigYaml extends HelmChartYaml { }, }) } + + private setBesuConfigs(metrics = false) { + this.setBesuFlags({ + privacy: false, + removeKeysOnDelete: false, + isBootnode: false, + usesBootnodes: false, + }) + + this.setBesuNode({ + besu: { + metrics: { + serviceMonitorEnabled: metrics, + }, + resources: { + cpuLimit: 0.7, + cpuRequest: 0.5, + memLimit: '2G', + memRequest: '1G', + }, + account: { + password: 'password', + }, + }, + }) + } } export default MemberConfigYaml diff --git a/src/eth/model/yaml/helm-chart/validatorYaml.ts b/src/eth/model/yaml/helm-chart/validatorYaml.ts index dfa44d70..2f8707ab 100644 --- a/src/eth/model/yaml/helm-chart/validatorYaml.ts +++ b/src/eth/model/yaml/helm-chart/validatorYaml.ts @@ -1,7 +1,18 @@ import HelmChartYaml from './helmChartYaml' +import { NetworkType } from '../../../config/network.type' class ValidatorConfigYaml extends HelmChartYaml { - public setQuorumConfigs (metrics = false) { + public setValidator(networkType: NetworkType, metrics = false) { + if (networkType === 'quorum') { + this.setQuorumConfigs(metrics) + } else if (networkType === 'besu') { + this.setBesuConfigs(metrics) + } else { + throw new Error(`Unsupported network type: ${networkType}`) + } + } + + private setQuorumConfigs(metrics = false) { this.setQuorumFlags({ privacy: false, removeKeysOnDelete: false, @@ -9,10 +20,9 @@ class ValidatorConfigYaml extends HelmChartYaml { usesBootnodes: false, }) - this.setNode({ + this.setQuorumNode({ goquorum: { metrics: { - // default value in helm is true serviceMonitorEnabled: metrics, }, resources: { @@ -24,6 +34,29 @@ class ValidatorConfigYaml extends HelmChartYaml { }, }) } + + private setBesuConfigs(metrics = false) { + this.setBesuFlags({ + privacy: false, + removeKeysOnDelete: false, + isBootnode: false, + usesBootnodes: false, + }) + + this.setBesuNode({ + besu: { + metrics: { + serviceMonitorEnabled: metrics, + }, + resources: { + cpuLimit: 0.7, + cpuRequest: 0.5, + memLimit: '2G', + memRequest: '1G', + }, + }, + }) + } } export default ValidatorConfigYaml diff --git a/src/eth/service/cluster.ts b/src/eth/service/cluster.ts index 957fcb28..20f2fceb 100644 --- a/src/eth/service/cluster.ts +++ b/src/eth/service/cluster.ts @@ -6,34 +6,40 @@ 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' +import fs from 'fs' + export default class Cluster extends AbstractService { /** * @description Use helm create quorum template */ public async apply (networkCreateConfig: ClusterCreateType, spinner: Ora): Promise { - const { provider, region, chainId, validatorNumber, memberNumber } = networkCreateConfig + const { provider, region, chainId, validatorNumber, memberNumber, networkType } = networkCreateConfig + if (!networkType) { + throw new Error('Network type is not defined') + } // create genesis and account const k8s = new KubernetesInstance(this.config, this.infra, this.kubernetesInfra) this.bdkFile.checkHelmChartPath() const genesisYaml = new GenesisConfigYaml() genesisYaml.setProvider(provider, region) - genesisYaml.setGenesis(chainId, validatorNumber) - + genesisYaml.setGenesis(networkType, chainId, validatorNumber) this.bdkFile.createGenesisChartValues(genesisYaml) // custom namespace spinner.start('Helm install genesis chart') const genesisOutput = await k8s.install({ - helmChart: this.bdkFile.getGoQuorumGenesisChartPath(), + helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumGenesisChartPath() : this.bdkFile.getBesuGenesisChartPath(), name: 'genesis', - namespace: 'quorum', + namespace: networkType, values: this.bdkFile.getGenesisChartPath(), }) as DockerResultType - await k8s.wait('job.batch/goquorum-genesis-init', 'quorum') + const namespaceForJob = networkType === 'quorum' ? 'goquorum' : networkType; + await k8s.wait(`job.batch/${namespaceForJob}-genesis-init`, networkType) spinner.succeed(`Helm install genesis chart ${genesisOutput.stdout}`) // create network const validatorYaml = new ValidatorConfigYaml() validatorYaml.setProvider(provider, region) - validatorYaml.setQuorumConfigs() + validatorYaml.setValidator(networkType) for (let i = 0; i < validatorNumber; i += 1) { this.bdkFile.createValidatorChartValues(validatorYaml, i) @@ -41,26 +47,29 @@ export default class Cluster extends AbstractService { const memberYaml = new MemberConfigYaml() memberYaml.setProvider(provider, region) - memberYaml.setQuorumConfigs() + memberYaml.setMember(networkType) for (let i = 0; i < memberNumber; i += 1) { this.bdkFile.createMemberChartValues(memberYaml, i) } for (let i = 0; i < validatorNumber; i += 1) { spinner.start(`Helm install validator chart ${i + 1}`) + const valuesPath = this.bdkFile.getValidatorChartPath(i); + console.log(`Validator ${i + 1} values file content:`); + console.log(await fs.promises.readFile(valuesPath, 'utf8')); const validatorOutput = await k8s.install({ - helmChart: this.bdkFile.getGoQuorumNodeChartPath(), + helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumNodeChartPath() : this.bdkFile.getBesuNodeChartPath(), name: `validator-${i + 1}`, - namespace: 'quorum', - values: this.bdkFile.getValidatorChartPath(i), + namespace: networkType, + values: valuesPath, }) as DockerResultType spinner.succeed(`Helm install validator chart ${i + 1} ${validatorOutput.stdout}`) } for (let i = 0; i < memberNumber; i += 1) { spinner.start(`Helm install member chart ${i + 1}`) const memberOutput = await k8s.install({ - helmChart: this.bdkFile.getGoQuorumNodeChartPath(), + helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumNodeChartPath() : this.bdkFile.getBesuNodeChartPath(), name: `member-${i + 1}`, - namespace: 'quorum', + namespace: networkType, values: this.bdkFile.getMemberChartPath(i), }) as DockerResultType spinner.succeed(`Helm install member chart ${i + 1} ${memberOutput.stdout}`) @@ -74,18 +83,18 @@ export default class Cluster extends AbstractService { clusterGenerateConfig: ClusterGenerateType, networkCreateConfig: ClusterCreateType, ): Promise { - const { provider, region, chainId, validatorNumber, memberNumber } = networkCreateConfig + const { provider, region, chainId, validatorNumber, memberNumber, networkType } = networkCreateConfig this.bdkFile.checkHelmChartPath() // create genesis and account const genesisYaml = new GenesisConfigYaml() genesisYaml.setProvider(provider, region) - genesisYaml.setGenesis(chainId, validatorNumber) + genesisYaml.setGenesis(networkType, chainId, validatorNumber) this.bdkFile.createGenesisChartValues(genesisYaml) const validatorYaml = new ValidatorConfigYaml() validatorYaml.setProvider(provider, region) - validatorYaml.setQuorumConfigs() + validatorYaml.setValidator(networkType) for (let i = 0; i < validatorNumber; i += 1) { this.bdkFile.createValidatorChartValues(validatorYaml, i) @@ -93,7 +102,7 @@ export default class Cluster extends AbstractService { const memberYaml = new MemberConfigYaml() memberYaml.setProvider(provider, region) - memberYaml.setQuorumConfigs() + memberYaml.setMember(networkType) for (let i = 0; i < memberNumber; i += 1) { this.bdkFile.createMemberChartValues(memberYaml, i) } @@ -101,27 +110,27 @@ export default class Cluster extends AbstractService { if (clusterGenerateConfig.chartPackageModeEnabled) { const k8s = new KubernetesInstance(this.config, this.infra, this.kubernetesInfra) const genesisOutput = await k8s.template({ - helmChart: this.bdkFile.getGoQuorumGenesisChartPath(), + helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumGenesisChartPath() : this.bdkFile.getBesuGenesisChartPath(), name: 'genesis', - namespace: 'quorum', + namespace: networkType, values: this.bdkFile.getGenesisChartPath(), }) as DockerResultType this.bdkFile.createYaml('genesis', genesisOutput.stdout) for (let i = 0; i < validatorNumber; i += 1) { const validatorOutput = await k8s.template({ - helmChart: this.bdkFile.getGoQuorumNodeChartPath(), + helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumNodeChartPath() : this.bdkFile.getBesuNodeChartPath(), name: `validator-${i + 1}`, - namespace: 'quorum', + namespace: networkType, values: this.bdkFile.getValidatorChartPath(i), }) as DockerResultType this.bdkFile.createYaml(`validator-${i + 1}`, validatorOutput.stdout) } for (let i = 0; i < memberNumber; i += 1) { const memberOutput = await k8s.template({ - helmChart: this.bdkFile.getGoQuorumNodeChartPath(), + helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumNodeChartPath() : this.bdkFile.getBesuNodeChartPath(), name: `member-${i + 1}`, - namespace: 'quorum', + namespace: networkType, values: this.bdkFile.getMemberChartPath(i), }) as DockerResultType this.bdkFile.createYaml(`member-${i + 1}`, memberOutput.stdout) @@ -137,7 +146,17 @@ export default class Cluster extends AbstractService { const k8s = new KubernetesInstance(this.config, this.infra, this.kubernetesInfra) const releases = await this.getAllHelmRelease() await Promise.all(releases.map(async (release: string) => { - await k8s.delete({ name: release, namespace: 'quorum' }) + try { + await k8s.delete({ name: release, namespace: 'quorum' }) + } catch (error) { + console.log(`Failed to delete release ${release} from quorum namespace:`) + } + + try { + await k8s.delete({ name: release, namespace: 'besu' }) + } catch (error) { + console.log(`Failed to delete release ${release} from besu namespace: `) + } })) } From 57a57d3422e0e8e9f5c6dbb22f3d0ac14c80a9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AC=9D=E6=98=8E=E8=8F=AF?= Date: Wed, 28 Aug 2024 14:21:19 +0800 Subject: [PATCH 5/6] feat: add Kubernetes configuration files for Besu This commit introduces Kubernetes configuration files for deploying Besu nodes. Key additions include: - Helm charts for Besu genesis and node deployment - Kubernetes manifests for Besu network setup - Configuration files for Besu node operations in a Kubernetes environment --- src/eth/command/backup/export.ts | 1 - src/eth/command/cluster/apply.ts | 8 +- src/eth/command/cluster/generate.ts | 5 +- src/eth/config/besu/besuMemberConfig.ts | 2 +- src/eth/config/networkConfigLoader.ts | 4 +- src/eth/instance/bdkFile.ts | 1 + .../charts/besu-genesis/.helmignore | 23 ++ .../kubernetes/charts/besu-genesis/Chart.yaml | 20 ++ .../besu-genesis/templates/_helpers.tpl | 29 ++ .../templates/genesis-job-cleanup.yaml | 63 ++++ .../templates/genesis-job-init.yaml | 167 +++++++++ .../templates/genesis-service-account.yaml | 45 +++ .../charts/besu-genesis/values.yaml | 50 +++ .../kubernetes/charts/besu-node/.helmignore | 23 ++ .../kubernetes/charts/besu-node/Chart.yaml | 20 ++ .../charts/besu-node/templates/_helpers.tpl | 29 ++ .../templates/aws-secret-provider-class.yaml | 38 ++ .../azure-secret-provider-class.yaml | 51 +++ .../templates/besu-config-configmap.yaml | 110 ++++++ .../templates/node-hooks-pre-delete.yaml | 167 +++++++++ .../templates/node-hooks-pre-install.yaml | 197 +++++++++++ .../templates/node-hooks-service-account.yaml | 55 +++ .../templates/node-service-account.yaml | 44 +++ .../besu-node/templates/node-service.yaml | 96 +++++ .../besu-node/templates/node-statefulset.yaml | 333 ++++++++++++++++++ .../besu-node/templates/node-storage.yaml | 70 ++++ .../templates/permissions-configmap.yaml | 20 ++ .../kubernetes/charts/besu-node/values.yaml | 158 +++++++++ src/eth/model/type/network.type.ts | 2 +- src/eth/model/yaml/helm-chart/genesisYaml.ts | 6 +- .../model/yaml/helm-chart/helmChartYaml.ts | 13 +- src/eth/model/yaml/helm-chart/memberYaml.ts | 4 +- .../model/yaml/helm-chart/validatorYaml.ts | 6 +- src/eth/service/cluster.ts | 10 +- src/eth/service/network.ts | 2 +- 35 files changed, 1836 insertions(+), 36 deletions(-) create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/.helmignore create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/Chart.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/_helpers.tpl create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-cleanup.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-init.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-service-account.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-genesis/values.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/.helmignore create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/Chart.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/_helpers.tpl create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/aws-secret-provider-class.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/azure-secret-provider-class.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/besu-config-configmap.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-delete.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-install.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-service-account.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service-account.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-statefulset.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-storage.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/templates/permissions-configmap.yaml create mode 100644 src/eth/instance/infra/kubernetes/charts/besu-node/values.yaml diff --git a/src/eth/command/backup/export.ts b/src/eth/command/backup/export.ts index df083178..084abc24 100644 --- a/src/eth/command/backup/export.ts +++ b/src/eth/command/backup/export.ts @@ -10,7 +10,6 @@ export const command = 'export' export const desc = '匯出現有的 Eth Network' - interface OptType { interactive: boolean } diff --git a/src/eth/command/cluster/apply.ts b/src/eth/command/cluster/apply.ts index 6266ba86..19b4525c 100644 --- a/src/eth/command/cluster/apply.ts +++ b/src/eth/command/cluster/apply.ts @@ -9,9 +9,7 @@ import { WalletType } from '../../../wallet/model/type/wallet.type' import { defaultNetworkConfig } from '../../model/defaultNetworkConfig' import prompts from 'prompts' import ora from 'ora' -import { getNetworkTypeChoices } from '../../config/network.type' -import { NetworkType } from '../../config/network.type' - +import { getNetworkTypeChoices, NetworkType } from '../../config/network.type' export const command = 'apply' export const desc = '產生 Network Cluster 所需的相關設定檔案並建立網路' @@ -44,13 +42,13 @@ export const handler = async (argv: Arguments) => { const confirmDelete = (await prompts({ type: 'confirm', name: 'value', - message: `⚠️ Detecting ${networkType} cluster already exists. The following processes will remove all existing files. Continue?`, + message: '⚠️ Detecting 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() cluster.removeHelmChartFiles() - spinner.succeed(`Remove all existing files!`) + spinner.succeed('Remove all existing files!') } return confirmDelete } else { diff --git a/src/eth/command/cluster/generate.ts b/src/eth/command/cluster/generate.ts index f0665bca..37fe0405 100644 --- a/src/eth/command/cluster/generate.ts +++ b/src/eth/command/cluster/generate.ts @@ -9,8 +9,7 @@ import { defaultNetworkConfig } from '../../model/defaultNetworkConfig' import { onCancel } from '../../../util/error' import prompts from 'prompts' import ora from 'ora' -import { getNetworkTypeChoices } from '../../config/network.type' -import { NetworkType } from '../../config/network.type' +import { getNetworkTypeChoices, NetworkType } from '../../config/network.type' export const command = 'generate' @@ -44,7 +43,7 @@ export const handler = async (argv: Arguments) => { const confirmDelete = (await prompts({ type: 'confirm', name: 'value', - message: `⚠️ Detecting ${networkType} cluster already exists. The following processes will remove all existing files. Continue?`, + message: '⚠️ Detecting cluster already exists. The following processes will remove all existing files. Continue?', initial: false, }, { onCancel })).value if (confirmDelete) { diff --git a/src/eth/config/besu/besuMemberConfig.ts b/src/eth/config/besu/besuMemberConfig.ts index d7efa56b..5c7ea907 100644 --- a/src/eth/config/besu/besuMemberConfig.ts +++ b/src/eth/config/besu/besuMemberConfig.ts @@ -5,7 +5,7 @@ const besuConfig: NetworkConfigType = { networks: [NetworkType.BESU], entrypoint: (chainId, peerPort, bootnode, nodeEncode) => [ '/bin/sh', '-c', - `besu --data-path=/data \ + `besu --data-path=/data \ --genesis-file=/data/genesis.json \ --network-id=${chainId} \ ${(bootnode) ? '--bootnodes '.concat(nodeEncode) : ''}\ diff --git a/src/eth/config/networkConfigLoader.ts b/src/eth/config/networkConfigLoader.ts index 808ef8e1..fb1fac34 100644 --- a/src/eth/config/networkConfigLoader.ts +++ b/src/eth/config/networkConfigLoader.ts @@ -8,7 +8,7 @@ import quorumGenesisConfig from './quorum/quorumGenesisConfig' import besuGenesisConfig from './besu/besuGenesisConfig' import { NodeTypeEnum } from '../model/type/config.type' -const networkConfigs: { [key in NetworkType]: { member: NetworkConfigType; validator: NetworkConfigType; genesisJson: GenesisJsonType, ethereumJsonRpcVariant: String } } = { +const networkConfigs: { [key in NetworkType]: { member: NetworkConfigType; validator: NetworkConfigType; genesisJson: GenesisJsonType; ethereumJsonRpcVariant: string } } = { [NetworkType.BESU]: { member: besuMemberConfig, validator: besuValidatorConfig, @@ -38,7 +38,7 @@ export const getGenesisJson = (networkType: NetworkType): GenesisJsonType => { } return genesisJson } -export const getEthereumJsonRpcVariant = (networkType: NetworkType): String => { +export const getEthereumJsonRpcVariant = (networkType: NetworkType): string => { const ethereumJsonRpcVariant = networkConfigs[networkType].ethereumJsonRpcVariant if (!ethereumJsonRpcVariant) { throw new Error(`Unsupported network type: ${networkType}`) diff --git a/src/eth/instance/bdkFile.ts b/src/eth/instance/bdkFile.ts index 99fa02cc..7999a81c 100644 --- a/src/eth/instance/bdkFile.ts +++ b/src/eth/instance/bdkFile.ts @@ -288,6 +288,7 @@ export default class BdkFile { this.checkHelmChartPath() return `${this.helmPath}/goquorum-genesis` } + public getBesuGenesisChartPath (): string { this.checkHelmChartPath() return `${this.helmPath}/besu-genesis` diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/.helmignore b/src/eth/instance/infra/kubernetes/charts/besu-genesis/.helmignore new file mode 100644 index 00000000..253226cb --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +generated_config/ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/Chart.yaml b/src/eth/instance/infra/kubernetes/charts/besu-genesis/Chart.yaml new file mode 100644 index 00000000..c0025fc4 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +version: 0.1.0 +appVersion: latest +name: besu-genesis +description: Besu Genesis generator with Helm chart in Kubernetes +keywords: + - ethereum + - besu + - hyperledger + - enterprise + - blockchain + - pegasys + - consensys +home: https://besu.hyperledger.org +sources: + - https://github.com/hyperledger/besu +maintainers: + - name: Joshua Fernandes + email: joshua.fernandes@consensys.net +icon: http://besu.hyperledger.org/en/latest/favicon.ico \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/_helpers.tpl b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/_helpers.tpl new file mode 100644 index 00000000..00bdbb9d --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/_helpers.tpl @@ -0,0 +1,29 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "besu-genesis.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "besu-genesis.fullname" -}} +{{- $name := default .Chart.Name -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $name .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "besu-genesis.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-cleanup.yaml b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-cleanup.yaml new file mode 100644 index 00000000..73ced5c9 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-cleanup.yaml @@ -0,0 +1,63 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "besu-genesis.name" . }}-cleanup + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: besu-genesis-job-cleanup + app.kubernetes.io/component: genesis-job-cleanup + app.kubernetes.io/part-of: {{ include "besu-genesis.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/managed-by: helm + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-delete" + helm.sh/hook-delete-policy: "hook-succeeded" +spec: + backoffLimit: 3 + completions: 1 + template: + metadata: + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end}} + app.kubernetes.io/name: besu-genesis-job-cleanup + app.kubernetes.io/component: genesis-job-cleanup + app.kubernetes.io/part-of: {{ include "besu-genesis.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/managed-by: helm + spec: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.aws.serviceAccountName }} +{{- else }} + serviceAccountName: {{ include "besu-genesis.name" . }}-sa +{{- end }} + restartPolicy: "Never" + containers: + - name: delete-genesis + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + securityContext: + runAsUser: 0 + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /bin/bash + - -c + args: + - | + +{{- if .Values.quorumFlags.removeGenesisOnDelete }} + + echo "Deleting genesis configmap in k8s ..." + kubectl delete configmap --namespace {{ .Release.Namespace }} besu-genesis + + echo "Deleting node-enodes configmap in k8s ..." + kubectl delete configmap --namespace {{ .Release.Namespace }} besu-peers + +{{- end}} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-init.yaml b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-init.yaml new file mode 100644 index 00000000..fd519988 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-job-init.yaml @@ -0,0 +1,167 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "besu-genesis.name" . }}-init + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: besu-genesis-job + app.kubernetes.io/component: genesis-job + app.kubernetes.io/part-of: {{ include "besu-genesis.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/hook-delete-policy: "hook-succeeded" +spec: + # backoffLimit: 3 + completions: 1 + template: + metadata: + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: besu-genesis-job + app.kubernetes.io/component: genesis-job + app.kubernetes.io/part-of: {{ include "besu-genesis.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/managed-by: helm + spec: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.aws.serviceAccountName }} +{{- else }} + serviceAccountName: {{ include "besu-genesis.name" . }}-sa +{{- end }} + restartPolicy: "Never" + containers: + - name: generate-genesis + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + securityContext: + runAsUser: 0 + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - name: generated-config + mountPath: /generated-config + command: + - /bin/bash + - -c + args: + - | +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + function safeWriteSecret { + key=$1 + fpath=$2 + az keyvault secret show --vault-name {{ .Values.azure.keyvaultName }} --name $key > /dev/null 2>&1 + if [ $? -ne 0 ]; then + az keyvault secret set --vault-name {{ .Values.azure.keyvaultName }} --name $key --file $fpath --encoding utf-8 + else + # if the key exists pull it from keyvault so that when you update the enodes configmap, you have the right value + az keyvault secret show --vault-name {{ .Values.azure.keyvaultName }} --name $key | jq -r '.value' > $fpath + fi + } + az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u {{ .Values.azure.identityClientId }} -t {{ .Values.azure.tenantId }} + az account set --subscription {{ .Values.azure.subscriptionId }} + +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + + function safeWriteSecret { + key=$1 + fpath=$2 + aws secretsmanager describe-secret --secret-id $key > /dev/null 2>&1 + if [ $? -ne 0 ]; then + aws secretsmanager create-secret --name $key --description $key --secret-string file://$fpath + else + # if the key exists pull it from keyvault so that when you update the enodes configmap, you have the right value + aws secretsmanager get-secret-value --secret-id $key | jq -r '.SecretString' > $fpath + fi + } + +{{- else }} + + function safeWriteSecret { + key=$1 + fpath=$2 + kubectl create secret generic ${key}-keys --namespace {{ .Release.Namespace }} --from-file=nodekey=${fpath}/nodekey --from-file=nodekey.pub=${fpath}/nodekey.pub --from-file=enode=${fpath}/nodekey.pub --from-file=accountPrivate.key=${fpath}/accountPrivateKey --from-file=accountPassword=${fpath}/accountPassword --from-file=accountKeystore=${fpath}/accountKeystore --from-file=accountAdddress=${fpath}/accountAddress + } + +{{- end }} + + function safeWriteBesuPeersConfigmap { + FOLDER_PATH=$1 + kubectl get configmap --namespace {{ .Release.Namespace }} besu-peers + if [ $? -ne 0 ]; then + kubectl create configmap --namespace {{ .Release.Namespace }} besu-peers --from-file=static-nodes.json=$FOLDER_PATH/static-nodes.json + fi + } + + function safeWriteGenesisConfigmap { + FOLDER_PATH=$1 + kubectl get configmap --namespace {{ .Release.Namespace }} besu-genesis + if [ $? -ne 0 ]; then + kubectl create configmap --namespace {{ .Release.Namespace }} besu-genesis --from-file=genesis.json=$FOLDER_PATH/besu/genesis.json + fi + } + + echo "Creating config ..." + FOLDER_PATH=$(quorum-genesis-tool --consensus {{ .Values.rawGenesisConfig.genesis.config.algorithm.consensus }} {{ if .Values.rawGenesisConfig.blockchain.nodes.generate }} --validators {{ .Values.rawGenesisConfig.blockchain.nodes.count }} {{ else }} --validators 0 {{ end }} --members 0 --bootnodes 0 --chainID {{ .Values.rawGenesisConfig.genesis.config.chainId }} --blockperiod {{ .Values.rawGenesisConfig.genesis.config.algorithm.blockperiodseconds }} --epochLength {{ .Values.rawGenesisConfig.genesis.config.algorithm.epochlength }} --requestTimeout {{ .Values.rawGenesisConfig.genesis.config.algorithm.requesttimeoutseconds }} --difficulty {{ .Values.rawGenesisConfig.genesis.difficulty }} --gasLimit {{ .Values.rawGenesisConfig.genesis.gasLimit }} --coinbase {{ .Values.rawGenesisConfig.genesis.coinbase }} {{ if .Values.rawGenesisConfig.blockchain.accountPassword }} --accountPassword {{ .Values.rawGenesisConfig.blockchain.accountPassword }} {{ end }} --quickstartDevAccounts {{ .Values.rawGenesisConfig.genesis.includeQuickStartAccounts }} --alloc {{ if .Values.rawGenesisConfig.genesis.alloc }} '{{ .Values.rawGenesisConfig.genesis.alloc | toJson }}' {{ else }} '{}' {{ end }} --outputPath /generated-config | tail -1 | sed -e "s/^Artifacts in folder: //") + + echo "Creating bootnodes configmap in k8s ..." + echo "[]" > /tmp/besu-bootnodes + kubectl create configmap --namespace {{ .Release.Namespace }} besu-bootnodes --from-file=bootnodes=/tmp/besu-bootnodes + + echo $FOLDER_PATH + echo "Creating genesis configmap in k8s ..." + safeWriteGenesisConfigmap $FOLDER_PATH + + # create the static-nodes with proper dns names for the quorum nodes + echo "[" > $FOLDER_PATH/static-nodes.json + echo "Creating validator secrets in k8s ..." + i=1 + for f in $(find $FOLDER_PATH -type d -iname "validator*" -exec basename {} \;); do + if [ -d $FOLDER_PATH/${f} ]; then + echo $f + echo "Creating keys in vault for validator-${i} ..." + +{{- if and (ne .Values.cluster.provider "local") (.Values.cluster.cloudNativeServices) }} + + safeWriteSecret besu-node-validator-${i}-nodekey $FOLDER_PATH/${f}/nodekey + safeWriteSecret besu-node-validator-${i}-nodekeypub $FOLDER_PATH/${f}/nodekey.pub + safeWriteSecret besu-node-validator-${i}-enode $FOLDER_PATH/${f}/nodekey.pub + safeWriteSecret besu-node-validator-${i}-address $FOLDER_PATH/${f}/address + kubectl create configmap --namespace {{ .Release.Namespace }} besu-node-validator-${i}-address --from-file=address=$FOLDER_PATH/${f}/address + + safeWriteSecret besu-node-validator-${i}-accountPrivateKey $FOLDER_PATH/${f}/accountPrivateKey + safeWriteSecret besu-node-validator-${i}-accountPassword $FOLDER_PATH/${f}/accountPassword + safeWriteSecret besu-node-validator-${i}-accountKeystore $FOLDER_PATH/${f}/accountKeystore + safeWriteSecret besu-node-validator-${i}-accountAddress $FOLDER_PATH/${f}/accountAddress + +{{- else }} + + safeWriteSecret besu-node-validator-${i} "$FOLDER_PATH/${f}" + kubectl create configmap --namespace {{ .Release.Namespace }} besu-node-validator-${i}-address --from-file=address=$FOLDER_PATH/${f}/address + +{{- end }} + # add to the static-nodes + pubkey=$(cat $FOLDER_PATH/${f}/nodekey.pub ) + echo ",\"enode://$pubkey@besu-node-validator-$i-0.besu-node-validator-$i.{{ .Release.Namespace }}.svc.cluster.local:30303?discport=0\"" >> $FOLDER_PATH/static-nodes.json + + i=$((i+1)) + fi + done + + echo "]" >> $FOLDER_PATH/static-nodes.json + # remove the extra comma to make it valid json + sed -i '0,/,/s///' $FOLDER_PATH/static-nodes.json + safeWriteBesuPeersConfigmap $FOLDER_PATH + + echo "Completed ..." + + volumes: + - name: generated-config + emptyDir: {} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-service-account.yaml b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-service-account.yaml new file mode 100644 index 00000000..666fabb7 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/templates/genesis-service-account.yaml @@ -0,0 +1,45 @@ + +{{- if not .Values.cluster.cloudNativeServices }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "besu-genesis.name" . }}-sa + namespace: {{ .Release.Namespace }} + +{{- end }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "besu-genesis.name" . }}-role + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["secrets", "configmaps"] + verbs: ["create", "get", "list", "update", "delete" ] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch" ] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "besu-genesis.name" . }}-rb + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "besu-genesis.name" . }}-role +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + name: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + name: {{ .Values.aws.serviceAccountName }} +{{- else }} + name: {{ include "besu-genesis.name" . }}-sa +{{- end}} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-genesis/values.yaml b/src/eth/instance/infra/kubernetes/charts/besu-genesis/values.yaml new file mode 100644 index 00000000..b35ac4a9 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-genesis/values.yaml @@ -0,0 +1,50 @@ +--- + +quorumFlags: + removeGenesisOnDelete: true + +cluster: + provider: local # choose from: local | aws | azure + cloudNativeServices: false # set to true to use Cloud Native Services (SecretsManager and IAM for AWS; KeyVault & Managed Identities for Azure) + +aws: + # the aws cli commands uses the name 'quorum-sa' so only change this if you altered the name + serviceAccountName: quorum-sa + # the region you are deploying to + region: ap-southeast-2 + +azure: + serviceAccountName: quorum-sa + # the clientId of the user assigned managed identity created in the template + identityClientId: azure-clientId + keyvaultName: azure-keyvault + # the tenant ID of the key vault + tenantId: azure-tenantId + # the subscription ID to use - this needs to be set explicitly when using multi tenancy + subscriptionId: azure-subscriptionId + +# the raw Genesis config +# rawGenesisConfig.blockchain.nodes set the number of validators/signers +rawGenesisConfig: + genesis: + config: + chainId: 1337 + algorithm: + consensus: qbft + blockperiodseconds: 10 + epochlength: 30000 + requesttimeoutseconds: 20 + gasLimit: '0xf7b760' + difficulty: '0x1' + coinbase: '0x0000000000000000000000000000000000000000' + blockchain: + nodes: + generate: true + count: 4 + accountPassword: 'password' + + +image: + repository: consensys/quorum-k8s-hooks + tag: qgt-0.2.15 + pullPolicy: IfNotPresent \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/.helmignore b/src/eth/instance/infra/kubernetes/charts/besu-node/.helmignore new file mode 100644 index 00000000..253226cb --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +generated_config/ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/Chart.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/Chart.yaml new file mode 100644 index 00000000..5b0e1b8c --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +version: 0.1.0 +appVersion: 22.1.3 +name: besu-node +description: Besu nodes for a POA network +keywords: + - ethereum + - besu + - hyperledger + - enterprise + - blockchain + - pegasys + - consensys +home: https://besu.hyperledger.org +sources: + - https://github.com/hyperledger/besu +maintainers: + - name: Joshua Fernandes + email: joshua.fernandes@consensys.net +icon: http://besu.hyperledger.org/en/latest/favicon.ico diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/_helpers.tpl b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/_helpers.tpl new file mode 100644 index 00000000..ff3333d2 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/_helpers.tpl @@ -0,0 +1,29 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "besu-node.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "besu-node.fullname" -}} +{{- $name := default .Chart.Name -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $name .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "besu-node.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/aws-secret-provider-class.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/aws-secret-provider-class.yaml new file mode 100644 index 00000000..022065f7 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/aws-secret-provider-class.yaml @@ -0,0 +1,38 @@ +{{- if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: {{ include "besu-node.fullname" . }}-secret-provider + namespace: {{ .Release.Namespace }} +spec: + provider: aws + parameters: + objects: | + - objectName: {{ include "besu-node.fullname" . }}-nodekey + objectAlias: nodekey + objectType: secretsmanager + objectVersion: "" + - objectName: {{ include "besu-node.fullname" . }}-nodekeypub + objectAlias: nodekey.pub + objectType: secretsmanager + objectVersion: "" + - objectName: {{ include "besu-node.fullname" . }}-enode + objectAlias: enode + objectType: secretsmanager + objectVersion: "" + {{- if .Values.quorumFlags.privacy }} + - objectName: {{ include "besu-node.fullname" . }}-tmkey + objectAlias: tm.key + objectType: secretsmanager + objectVersion: "" + - objectName: {{ include "besu-node.fullname" . }}-tmkeypub + objectAlias: tm.pub + objectType: secretsmanager + objectVersion: "" + - objectName: {{ include "besu-node.fullname" . }}-tmpassword + objectAlias: tm.password + objectType: secretsmanager + objectVersion: "" + {{- end }} +{{- end }} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/azure-secret-provider-class.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/azure-secret-provider-class.yaml new file mode 100644 index 00000000..b9654f84 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/azure-secret-provider-class.yaml @@ -0,0 +1,51 @@ +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} +--- +apiVersion: secrets-store.csi.x-k8s.io/v1alpha1 +kind: SecretProviderClass +metadata: + name: {{ include "besu-node.fullname" . }}-secret-provider + namespace: {{ .Release.Namespace }} +spec: + provider: azure + parameters: + usePodIdentity: "false" + useVMManagedIdentity: "true" + userAssignedIdentityID: "{{ .Values.azure.nodePoolIdentityClientId }}" + keyvaultName: "{{ .Values.azure.keyvaultName }}" + tenantId: "{{ .Values.azure.tenantId }}" + cloudName: "AzurePublicCloud" + objects: | + array: + - | + objectName: {{ include "besu-node.fullname" . }}-nodekey + objectAlias: nodekey + objectType: secret + objectVersion: "" + - | + objectName: {{ include "besu-node.fullname" . }}-nodekeypub + objectAlias: nodekey.pub + objectType: secret + objectVersion: "" + - | + objectName: {{ include "besu-node.fullname" . }}-enode + objectAlias: enode + objectType: secret + objectVersion: "" + {{- if .Values.quorumFlags.privacy }} + - | + objectName: {{ include "besu-node.fullname" . }}-tmkey + objectAlias: tm.key + objectType: secret + objectVersion: "" + - | + objectName: {{ include "besu-node.fullname" . }}-tmkeypub + objectAlias: tm.pub + objectType: secret + objectVersion: "" + - | + objectName: {{ include "besu-node.fullname" . }}-tmpassword + objectAlias: tm.password + objectType: secret + objectVersion: "" + {{- end }} +{{- end }} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/besu-config-configmap.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/besu-config-configmap.yaml new file mode 100644 index 00000000..eb77adef --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/besu-config-configmap.yaml @@ -0,0 +1,110 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "besu-node.fullname" . }}-besu-config + labels: + app.kubernetes.io/name: besu-config + app.kubernetes.io/component: besu + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm + namespace: {{ .Release.Namespace }} +data: + config.toml: |- + # Every possible CLI should be in this file. + # + # Please use a plausible value, besu has to at least be able to parse it. + # If it is a multi-valued CLI make it a TOML array. + # If it is a number or boolean make it a number or boolean + # All other config options are strings, and must be quoted. + + # Node Information + data-path={{ .Values.node.besu.dataPath | quote }} + genesis-file={{ .Values.node.besu.genesisFilePath | quote }} + logging={{ .Values.node.besu.logging | quote }} + node-private-key-file={{.Values.node.besu.privateKeyPath | quote }} + + {{ if .Values.node.besu.p2p.enabled -}} + # P2P network + p2p-enabled={{ .Values.node.besu.p2p.enabled }} + discovery-enabled={{ .Values.node.besu.p2p.discovery }} + static-nodes-file={{ .Values.node.besu.p2p.staticNodes | quote }} + p2p-host={{ .Values.node.besu.p2p.host | quote }} + p2p-port={{ .Values.node.besu.p2p.port }} + max-peers={{ .Values.node.besu.p2p.maxPeers }} + {{ end }} + + {{ if or .Values.node.besu.rpc.enabled .Values.node.besu.graphql.enabled .Values.node.besu.ws.enabled }} + host-allowlist={{ .Values.node.besu.http.allowlist }} + {{ end }} + + {{ if .Values.node.besu.rpc.enabled -}} + # JSON-RPC + rpc-http-enabled={{ .Values.node.besu.rpc.enabled }} + rpc-http-host={{ .Values.node.besu.rpc.host | quote }} + rpc-http-port={{ .Values.node.besu.rpc.port }} + rpc-http-api={{ .Values.node.besu.rpc.api }} + rpc-http-cors-origins={{ .Values.node.besu.rpc.corsOrigins }} + rpc-http-authentication-enabled={{ .Values.node.besu.rpc.authenticationEnabled }} + rpc-http-max-active-connections={{ .Values.node.besu.rpc.maxActiveConnections }} + revert-reason-enabled=true + {{ end }} + + {{ if .Values.node.besu.graphql.enabled -}} + # GRAPHQL-RPC + graphql-http-enabled={{ .Values.node.besu.graphql.enabled }} + graphql-http-host={{ .Values.node.besu.graphql.host | quote }} + graphql-http-port={{ .Values.node.besu.graphql.port }} + graphql-http-cors-origins={{ .Values.node.besu.graphql.corsOrigins }} + {{ end }} + + {{ if .Values.node.besu.ws.enabled -}} + # WebSockets API + rpc-ws-enabled={{ .Values.node.besu.ws.enabled }} + rpc-ws-host={{ .Values.node.besu.ws.host | quote }} + rpc-ws-port={{ .Values.node.besu.ws.port }} + rpc-ws-api={{ .Values.node.besu.ws.api }} + rpc-ws-authentication-enabled={{ .Values.node.besu.ws.authenticationEnabled }} + {{ end }} + + {{ if .Values.node.besu.permissions.enabled -}} + # Permissioning + permissions-nodes-config-file-enabled={{ .Values.node.besu.permissions.nodes.enabled }} + permissions-nodes-config-file={{ .Values.node.besu.permissions.filePath | quote }} + permissions-accounts-config-file-enabled={{ .Values.node.besu.permissions.accounts.enabled }} + permissions-accounts-config-file={{ .Values.node.besu.permissions.filePath | quote }} + permissions-nodes-contract-enabled={{ .Values.node.besu.permissions.nodesContract.enabled }} + permissions-nodes-contract-address={{ .Values.node.besu.permissions.nodesContract.address | quote }} + permissions-accounts-contract-enabled={{ .Values.node.besu.permissions.accountsContract.enabled }} + permissions-accounts-contract-address={{ .Values.node.besu.permissions.accountsContract.address | quote }} + {{ end }} + + {{ if .Values.quorumFlags.privacy -}} + # Privacy + privacy-enabled={{ .Values.quorumFlags.privacy }} + privacy-url={{ .Values.node.besu.privacy.url | quote }} + {{- if and (ne .Values.cluster.provider "local") (.Values.cluster.cloudNativeServices) }} + privacy-public-key-file="{{ .Values.node.besu.keysPath }}/{{ .Values.node.besu.privacy.pubkeyFile }}" + {{ else }} + privacy-public-key-file="{{ .Values.node.besu.privacy.pubkeysPath }}/{{ .Values.node.besu.privacy.pubkeyFile }}" + {{ end }} + privacy-onchain-groups-enabled={{ .Values.node.besu.privacy.onchainGroupsEnabled }} + {{ end }} + + {{ if .Values.node.besu.metrics.enabled -}} + # Metrics + metrics-enabled={{ .Values.node.besu.metrics.enabled }} + metrics-host={{ .Values.node.besu.metrics.host | quote }} + metrics-port={{ .Values.node.besu.metrics.port }} + {{ end }} + + {{ if .Values.node.besu.metricsPush.enabled -}} + # Metrics Push + metrics-push-enabled={{ .Values.node.besu.metricsPush.enabled }} + metrics-push-host={{ .Values.node.besu.metricsPush.host | quote }} + metrics-push-port={{ .Values.node.besu.metricsPush.port }} + metrics-push-interval={{ .Values.node.besu.metricsPush.interval }} + metrics-push-prometheus-job={{ .Values.node.besu.metricsPush.prometheusJob | quote }} + {{ end }} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-delete.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-delete.yaml new file mode 100644 index 00000000..4855d46b --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-delete.yaml @@ -0,0 +1,167 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "besu-node.fullname" . }}-pre-delete-hook + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/hook: pre-delete + helm.sh/hook-weight: "0" + helm.sh/hook-delete-policy: "hook-succeeded" + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: pre-delete-hook + app.kubernetes.io/component: job + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm +spec: + backoffLimit: 3 + completions: 1 + template: + metadata: + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end}} + app.kubernetes.io/name: pre-delete-hook + app.kubernetes.io/instance: {{ .Release.Name }} + spec: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.aws.serviceAccountName }} +{{- else }} + serviceAccountName: {{ include "besu-node.fullname" . }}-hooks-sa +{{- end }} + restartPolicy: "OnFailure" + containers: + - name: {{ template "besu-node.fullname" . }}-node-pre-delete-hook + image: "{{ .Values.image.hooks.repository }}:{{ .Values.image.hooks.tag }}" + imagePullPolicy: {{ .Values.image.hooks.pullPolicy }} + command: + - /bin/bash + - -c + args: + - | + + echo "{{ template "besu-node.fullname" . }} Pre Delete hook ..." + +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + + function deleteSecret { + key=$1 + fpath=$2 + az keyvault secret show --vault-name {{ .Values.azure.keyvaultName }} --name $key > /dev/null 2>&1 + if [ $? -eq 0 ]; then + az keyvault secret delete --vault-name {{ .Values.azure.keyvaultName }} --name $key + fi + } + + az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u {{ .Values.azure.identityClientId }} -t {{ .Values.azure.tenantId }} + az account set --subscription {{ .Values.azure.subscriptionId }} + +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + + function deleteSecret { + key=$1 + aws secretsmanager describe-secret --secret-id $key > /dev/null 2>&1 + if [ $? -eq 0 ]; then + aws secretsmanager delete-secret --secret-id $key --recovery-window-in-days 7 + fi + } + +{{- else }} + + function deleteSecret { + key=$1 + kubectl delete secret ${key} --namespace {{ .Release.Namespace }} + } + +{{- end }} + + function delete_node_from_tessera_peers_configmap { + kubectl -n {{ .Release.Namespace }} get configmap tessera-peers -o json + # if there is no configmap, do nothing + if [ $? -ne 0 ]; then + echo "No tessera-peers found, nothing to do..." + # delete the one + else + echo "tessera-peers found, deleting {{ template "besu-node.fullname" . }}..." + echo $(kubectl -n {{ .Release.Namespace }} get configmap tessera-peers -o jsonpath='{.data.tesseraPeers}' ) > /tmp/tessera-peers.raw + cat /tmp/tessera-peers.raw | jq --arg NEEDLE "{{ template "besu-node.fullname" . }}" 'del(.[] | select( .url | contains($NEEDLE) ))' > /tmp/tessera-peers + kubectl -n {{ .Release.Namespace }} create configmap tessera-peers --from-file=tesseraPeers=/tmp/tessera-peers -o yaml --dry-run=client | kubectl replace -f - + fi + } + + function delete_node_from_enodes_configmap { + kubectl -n {{ .Release.Namespace }} get configmap besu-peers -o json + # if there is no configmap, do nothing + if [ $? -ne 0 ]; then + echo "No peers found, nothing to do..." + # delete the one + else + echo "besu-peers found, deleting {{ template "besu-node.fullname" . }}..." + echo $(kubectl -n {{ .Release.Namespace }} get configmap besu-peers -o jsonpath='{.data.static-nodes\.json}' ) > /tmp/static-nodes.json.raw + cat /tmp/static-nodes.json.raw | jq --arg NEEDLE "{{ template "besu-node.fullname" . }}" 'del(.[] | select( . | contains($NEEDLE) ))' > /tmp/static-nodes.json + kubectl -n {{ .Release.Namespace }} create configmap besu-peers --from-file=static-nodes.json=/tmp/static-nodes.json -o yaml --dry-run=client | kubectl replace -f - + + echo "Deleting node address configmap... " + kubectl delete configmap {{ template "besu-node.fullname" . }}-address --namespace {{ .Release.Namespace }} + fi + } + + + function delete_node_from_besu_bootnodes_configmap { + kubectl -n {{ .Release.Namespace }} get configmap besu-bootnodes -o json + # if there is no configmap, do nothing + if [ $? -ne 0 ]; then + echo "No bootnodes found, nothing to do..." + # delete the one + else + echo "besu-bootnodes found, deleting {{ template "besu-node.fullname" . }}..." + echo $(kubectl -n {{ .Release.Namespace }} get configmap besu-bootnodes -o jsonpath='{.data.bootnodes-json}' ) > /tmp/besu-bootnodes-json.raw + cat /tmp/besu-bootnodes-json.raw | jq --arg NEEDLE "{{ template "besu-node.fullname" . }}" 'del(.[] | select( . | contains($NEEDLE) ))' > /tmp/besu-bootnodes-json + cat /tmp/besu-bootnodes-json | jq -r -c '. | join(",")' | tr -d '\n' > /tmp/besu-bootnodes-string + kubectl -n {{ .Release.Namespace }} create configmap besu-bootnodes --from-file=bootnodes-json=/tmp/besu-bootnodes-json --from-file=bootnodes-string=/tmp/besu-bootnodes-string -o yaml --dry-run=client | kubectl replace -f - + fi + } + + delete_node_from_enodes_configmap + delete_node_from_besu_bootnodes_configmap + delete_node_from_tessera_peers_configmap + +{{- if .Values.quorumFlags.removeKeysOnDelete }} + +{{- if and (ne .Values.cluster.provider "local") (.Values.cluster.cloudNativeServices) }} + + deleteSecret {{ template "besu-node.fullname" . }}-nodekey + deleteSecret {{ template "besu-node.fullname" . }}-nodekeypub + deleteSecret {{ template "besu-node.fullname" . }}-enode + deleteSecret {{ template "besu-node.fullname" . }}-accountPrivateKey + deleteSecret {{ template "besu-node.fullname" . }}-accountPassword + deleteSecret {{ template "besu-node.fullname" . }}-accountKeystore + deleteSecret {{ template "besu-node.fullname" . }}-accountAddress + deleteSecret {{ template "besu-node.fullname" . }}-address + +{{- if .Values.quorumFlags.privacy }} + deleteSecret {{ template "besu-node.fullname" . }}-tmkey + deleteSecret {{ template "besu-node.fullname" . }}-tmkeypub + deleteSecret {{ template "besu-node.fullname" . }}-tmpassword +{{- end }} + +{{- else }} + deleteSecret {{ template "besu-node.fullname" . }}-keys + deleteSecret {{ template "besu-node.fullname" . }}-account +{{- if .Values.quorumFlags.privacy }} + deleteSecret {{ template "besu-node.fullname" . }}-tessera-keys +{{- end }} + +{{- end }} + +{{- end }} + + echo "Completed" \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-install.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-install.yaml new file mode 100644 index 00000000..a79f95a5 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-pre-install.yaml @@ -0,0 +1,197 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "besu-node.fullname" . }}-pre-install-hook + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": "hook-succeeded" + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: pre-install-hook + app.kubernetes.io/component: job + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm +spec: + backoffLimit: 1 + completions: 1 + template: + metadata: + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: pre-install-hook + app.kubernetes.io/instance: {{ .Release.Name }} + spec: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.aws.serviceAccountName }} +{{- else }} + serviceAccountName: {{ include "besu-node.fullname" . }}-hooks-sa +{{- end }} + restartPolicy: "OnFailure" + containers: + - name: {{ template "besu-node.fullname" . }}-pre-start-hook + image: {{ .Values.image.hooks.repository }}:{{ .Values.image.hooks.tag }} + imagePullPolicy: {{ .Values.image.besu.pullPolicy }} + securityContext: + runAsUser: 0 + command: + - /bin/bash + - -c + args: + - | + + function update_peers_configmap { + PUBKEY_LOC=$1 + kubectl -n {{ .Release.Namespace }} get configmap besu-peers -o json + if [ $? -ne 0 ]; then + echo "[]" > /tmp/static-nodes.json.raw + else + echo $(kubectl -n {{ .Release.Namespace }} get configmap besu-peers -o jsonpath='{.data.static-nodes\.json}' ) > /tmp/static-nodes.json.raw + fi + # update the entries + echo "updating besu-peers..." + pubkey=$(cat $PUBKEY_LOC ) + NEEDLE="enode://$pubkey@{{ template "besu-node.fullname" . }}-0.{{ template "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:30303?discport=0" + cat /tmp/static-nodes.json.raw | jq --arg NEEDLE "$NEEDLE" '. += [ $NEEDLE ] | unique ' > /tmp/static-nodes.json + kubectl -n {{ .Release.Namespace }} create configmap besu-peers --from-file=static-nodes.json=/tmp/static-nodes.json -o yaml --dry-run=client | kubectl replace -f - + } + + function update_tessera_peers_configmap { + kubectl -n {{ .Release.Namespace }} get configmap tessera-peers -o json + # first time a tx node is deployed and there is no configmap + if [ $? -ne 0 ]; then + echo "No tessera-peers found, creating a new one..." + echo "[{ \"url\": \"http://{{ template "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:9000\" }]" > /tmp/tessera-peers + kubectl --namespace {{ .Release.Namespace }} create configmap tessera-peers --from-file=tesseraPeers=/tmp/tessera-peers + + # update the entries + else + echo "Tessera-peers found, updating existing..." + echo $(kubectl -n {{ .Release.Namespace }} get configmap tessera-peers -o jsonpath='{.data.tesseraPeers}' ) > /tmp/tessera-peers.raw + NEEDLE="http://{{ template "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:9000" + cat /tmp/tessera-peers.raw | jq --arg NEEDLE "$NEEDLE" '. += [{"url": $NEEDLE}] | unique ' > /tmp/tessera-peers + kubectl -n {{ .Release.Namespace }} create configmap tessera-peers --from-file=tesseraPeers=/tmp/tessera-peers -o yaml --dry-run=client | kubectl replace -f - + fi + } + + function update_bootnodes_configmap { + PUBKEY_LOC=$1 + kubectl -n {{ .Release.Namespace }} get configmap besu-bootnodes -o json + if [ $? -ne 0 ]; then + echo "[]" > /tmp/besu-bootnodes-json.raw + kubectl -n {{ .Release.Namespace }} create configmap besu-bootnodes --from-file=bootnodes-json=/tmp/besu-bootnodes-json.raw --from-literal=bootnodes-string="" + fi + + echo "updating besu-bootnodes..." + echo $(kubectl -n {{ .Release.Namespace }} get configmap besu-bootnodes -o jsonpath='{.data.bootnodes-json}' ) > /tmp/besu-bootnodes-json.raw + pubkey=$(cat $PUBKEY_LOC ) + NEEDLE="enode://$pubkey@{{ template "besu-node.fullname" . }}-0.{{ template "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:30303" + cat /tmp/besu-bootnodes-json.raw | jq --arg NEEDLE "$NEEDLE" '. += [ $NEEDLE ] | unique ' > /tmp/besu-bootnodes-json + cat /tmp/besu-bootnodes-json | jq -r -c '. | join(",")' | tr -d '\n' > /tmp/besu-bootnodes-string + kubectl -n {{ .Release.Namespace }} create configmap besu-bootnodes --from-file=bootnodes-json=/tmp/besu-bootnodes-json --from-file=bootnodes-string=/tmp/besu-bootnodes-string -o yaml --dry-run=client | kubectl replace -f - + } + + +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + function safeWriteSecret { + key=$1 + fpath=$2 + az keyvault secret show --vault-name {{ .Values.azure.keyvaultName }} --name $key > /dev/null 2>&1 + if [ $? -ne 0 ]; then + az keyvault secret set --vault-name {{ .Values.azure.keyvaultName }} --name $key --file $fpath --encoding utf-8 + else + # if the key exists pull it from keyvault so that when you update the enodes configmap, you have the right value + az keyvault secret show --vault-name {{ .Values.azure.keyvaultName }} --name $key | jq -r '.value' > $fpath + fi + } + + az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID + az account set --subscription {{ .Values.azure.subscriptionId }} + +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + function safeWriteSecret { + key=$1 + fpath=$2 + aws secretsmanager describe-secret --secret-id $key > /dev/null 2>&1 + if [ $? -ne 0 ]; then + aws secretsmanager create-secret --name $key --description $key --secret-string file://$fpath + else + # if the key exists pull it from keyvault so that when you update the enodes configmap, you have the right value + aws secretsmanager get-secret-value --secret-id $key | jq -r '.SecretString' > $fpath + fi + } +{{- else }} + + function safeWriteSecret { + key=$1 + fpath=$2 + kubectl get secret ${key}-keys --namespace {{ .Release.Namespace }} -o json > /dev/null 2>&1 + if [ $? -ne 0 ]; then + kubectl create secret generic ${key}-keys --namespace {{ .Release.Namespace }} --from-file=nodekey=${fpath}/nodekey --from-file=nodekey.pub=${fpath}/nodekey.pub --from-file=enode=${fpath}/nodekey.pub --from-file=accountPrivate.key=${fpath}/accountPrivateKey --from-file=accountPassword=${fpath}/accountPassword --from-file=accountKeystore=${fpath}/accountKeystore --from-file=accountAdddress=${fpath}/accountAddress + else + # if the key exists pull it from secrets so that when you update the enodes configmap, you have the right value + kubectl get secrets ${key}-keys --namespace {{ .Release.Namespace }} -o json | jq '.data.enode' | tr -d '"'| base64 --decode > /tmp/enode + fi + + kubectl get secret ${key}-tessera-keys --namespace {{ .Release.Namespace }} -o json > /dev/null 2>&1 + if [ $? -ne 0 ]; then + kubectl create secret generic {{ template "besu-node.fullname" . }}-tessera-keys --namespace {{ .Release.Namespace }} --from-file=tm.key=$FOLDER_PATH/member0/tessera.key --from-file=tm.pub=$FOLDER_PATH/member0/tessera.pub --from-file=tm.password=$FOLDER_PATH/member0/passwordFile.txt + fi + } +{{- end }} + + echo "{{ template "besu-node.fullname" . }} hook ..." + echo "Nodekey generation ..." + FOLDER_PATH=$(quorum-genesis-tool --validators 0 --members 1 --bootnodes 0 {{ if .Values.node.besu.account.password }} --accountPassword {{ .Values.node.besu.account.password }} {{ end }} --outputPath /generated-config | tail -1 | sed -e "s/^Artifacts in folder: //") + echo "Creating {{ template "besu-node.fullname" . }} secrets in k8s ..." + +{{- if .Values.cluster.cloudNativeServices }} + echo "Creating keys in vault for {{ template "besu-node.fullname" . }} ..." + safeWriteSecret {{ template "besu-node.fullname" . }}-nodekey $FOLDER_PATH/member0/nodekey + safeWriteSecret {{ template "besu-node.fullname" . }}-nodekeypub $FOLDER_PATH/member0/nodekey.pub + safeWriteSecret {{ template "besu-node.fullname" . }}-enode $FOLDER_PATH/member0/nodekey.pub + safeWriteSecret {{ template "besu-node.fullname" . }}-address $FOLDER_PATH/member0/address + safeWriteSecret {{ template "besu-node.fullname" . }}-accountPrivateKey $FOLDER_PATH/member0/accountPrivateKey + safeWriteSecret {{ template "besu-node.fullname" . }}-accountPassword $FOLDER_PATH/member0/accountPassword + safeWriteSecret {{ template "besu-node.fullname" . }}-accountKeystore $FOLDER_PATH/member0/accountKeystore + safeWriteSecret {{ template "besu-node.fullname" . }}-accountAddress $FOLDER_PATH/member0/accountAddress +{{- else }} + safeWriteSecret {{ template "besu-node.fullname" . }} $FOLDER_PATH/member0 +{{- end }} + cat $FOLDER_PATH/member0/nodekey.pub > /tmp/enode + echo "Creating configmap for node address" + kubectl create configmap {{ template "besu-node.fullname" . }}-address --from-file=address=$FOLDER_PATH/${f}/member0/address + + update_peers_configmap /tmp/enode +{{- if .Values.quorumFlags.isBootnode }} + update_bootnodes_configmap /tmp/enode +{{- end }} + echo "Completed" + +{{- if .Values.quorumFlags.privacy }} + FOLDER_PATH=$(quorum-genesis-tool --validators 0 --members 1 --bootnodes 0 --tesseraEnabled true --tesseraPassword {{ .Values.node.tessera.password }} --outputPath /tmp/tessera | tail -1 | sed -e "s/^Artifacts in folder: //") + if [ ! -f "$FOLDER_PATH/member0/passwordFile.txt" ]; then + echo "" > $FOLDER_PATH/member0/passwordFile.txt + fi + echo "Creating {{ template "besu-node.fullname" . }}-tessera-keys secrets in k8s ..." +{{- if .Values.cluster.cloudNativeServices }} + safeWriteSecret {{ template "besu-node.fullname" . }}-tmkey $FOLDER_PATH/member0/tessera.key + safeWriteSecret {{ template "besu-node.fullname" . }}-tmkeypub $FOLDER_PATH/member0/tessera.pub + safeWriteSecret {{ template "besu-node.fullname" . }}-tmpassword $FOLDER_PATH/member0/passwordFile.txt +{{- else }} + safeWriteSecret {{ template "besu-node.fullname" . }} $FOLDER_PATH/member0 +{{- end }} + update_tessera_peers_configmap + echo "Tessera Completed" +{{- end }} + echo "hook completed" \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-service-account.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-service-account.yaml new file mode 100644 index 00000000..df7026ab --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-hooks-service-account.yaml @@ -0,0 +1,55 @@ +{{- if not .Values.cluster.cloudNativeServices }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "besu-node.fullname" . }}-hooks-sa + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook-weight": "-2" + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "pre-install,pre-delete,post-delete" +{{- end }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "besu-node.fullname" . }}-hooks-role + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook-weight": "-2" + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "pre-install,pre-delete,post-delete" +rules: + - apiGroups: [""] + resources: ["secrets", "configmaps"] + verbs: ["create", "get", "list", "update", "delete", "patch" ] + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "besu-node.fullname" . }}-hooks-rb + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook-weight": "-1" + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "pre-install,pre-delete,post-delete" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "besu-node.fullname" . }}-hooks-role +subjects: +- kind: ServiceAccount + namespace: {{ .Release.Namespace }} +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + name: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + name: {{ .Values.aws.serviceAccountName }} +{{- else }} + name: {{ include "besu-node.fullname" . }}-hooks-sa +{{- end}} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service-account.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service-account.yaml new file mode 100644 index 00000000..475ab7b4 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service-account.yaml @@ -0,0 +1,44 @@ + +{{- if not .Values.cluster.cloudNativeServices }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "besu-node.fullname" . }}-sa + namespace: {{ .Release.Namespace }} +{{- end }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "besu-node.fullname" . }}-role + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "besu-node.fullname" . }}-rb + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "besu-node.fullname" . }}-role +subjects: +- kind: ServiceAccount + namespace: {{ .Release.Namespace }} +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + name: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + name: {{ .Values.aws.serviceAccountName }} +{{- else }} + name: {{ include "besu-node.fullname" . }}-sa +{{- end}} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service.yaml new file mode 100644 index 00000000..0723eec6 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-service.yaml @@ -0,0 +1,96 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "besu-node.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "besu-node.fullname" . }} + app.kubernetes.io/component: service + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm + namespace: {{ .Release.Namespace }} +spec: + type: ClusterIP + selector: + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + ports: + - name: json-rpc + port: {{ .Values.node.besu.rpc.port }} + targetPort: json-rpc + protocol: TCP + - name: ws + port: {{ .Values.node.besu.ws.port }} + targetPort: ws + protocol: TCP + - name: graphql + port: {{ .Values.node.besu.graphql.port }} + targetPort: graphql + protocol: TCP + - name: rlpx + port: {{ .Values.node.besu.p2p.port }} + targetPort: rlpx + protocol: TCP + - name: discovery + port: {{ .Values.node.besu.p2p.port }} + targetPort: discovery + protocol: UDP + - name: metrics + port: {{ .Values.node.besu.metrics.port }} + targetPort: metrics + protocol: TCP + +{{- if .Values.quorumFlags.privacy }} + - name: tessera + port: {{ .Values.node.tessera.port }} + targetPort: tessera + protocol: TCP + - name: tessera-tp + port: {{ .Values.node.tessera.tpport }} + targetPort: tessera-tp + protocol: TCP + - name: tessera-q2t + port: {{ .Values.node.tessera.q2tport }} + targetPort: tessera-q2t + protocol: TCP +{{- end }} + + +{{- if and .Values.node.besu.metrics.enabled .Values.node.besu.metrics.serviceMonitorEnabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "besu-node.fullname" . }}-servicemonitor + labels: + release: monitoring + helm.sh/chart: {{ include "besu-node.chart" . }} + app: {{ template "besu-node.fullname" . }} + chart: {{ template "besu-node.chart" . }} + heritage: {{ .Release.Service }} + namespace: {{ .Release.Namespace }} + app.kubernetes.io/name: {{ include "besu-node.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/component: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} +spec: + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "besu-node.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: {{ .Release.Name }} + endpoints: + - port: metrics + interval: 15s + path: /metrics + scheme: http + honorLabels: true +{{- end }} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-statefulset.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-statefulset.yaml new file mode 100644 index 00000000..a4326d2c --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-statefulset.yaml @@ -0,0 +1,333 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "besu-node.fullname" . }} + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: besu-statefulset + app.kubernetes.io/component: besu + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm + {{- range $labelName, $labelValue := .Values.node.besu.customLabels }} + {{ $labelName }}: {{ $labelValue }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + podManagementPolicy: OrderedReady + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: besu-statefulset + app.kubernetes.io/component: besu + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm + serviceName: {{ include "besu-node.fullname" . }} + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: {{ include "besu-node.fullname" . }}-storage + resources: + requests: + storage: "{{ .Values.storage.pvcSizeLimit }}" + template: + metadata: + labels: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + azure.workload.identity/use: "true" +{{- end }} + app.kubernetes.io/name: besu-statefulset + app.kubernetes.io/component: besu + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.node.besu.metrics.port | quote}} + prometheus.io/path: "/metrics" + spec: +{{- if and (eq .Values.cluster.provider "azure") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.azure.serviceAccountName }} +{{- else if and (eq .Values.cluster.provider "aws") (.Values.cluster.cloudNativeServices) }} + serviceAccountName: {{ .Values.aws.serviceAccountName }} +{{- else }} + serviceAccountName: {{ include "besu-node.fullname" . }}-sa +{{- end }} + initContainers: + +{{- if has .Values.cluster.provider .Values.volumePermissionsFix }} + # fix for minikube and PVC's only writable as root https://github.com/kubernetes/minikube/issues/1990 + - name: volume-permission-besu + image: busybox + command: ["sh", "-c", "chown -R 1000:1000 /data"] + volumeMounts: + - name: data + mountPath: /data + securityContext: + runAsUser: 0 +{{- end}} + + containers: + +{{- if .Values.quorumFlags.privacy }} + - name: {{ .Release.Name }}-tessera + image: {{ .Values.image.tessera.repository }}:{{ .Values.image.tessera.tag }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + resources: + requests: + cpu: "{{ .Values.node.tessera.resources.cpuRequest }}" + memory: "{{ .Values.node.tessera.resources.memRequest }}" + limits: + cpu: "{{ .Values.node.tessera.resources.cpuLimit }}" + memory: "{{ .Values.node.tessera.resources.memLimit }}" + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: TESSERA_CONFIG_TYPE + value: "-09" + volumeMounts: +{{- if and (ne .Values.cluster.provider "local") (.Values.cluster.cloudNativeServices) }} + - name: secrets-store + mountPath: {{ .Values.node.tessera.keysPath }} + readOnly: true +{{- else }} + - name: tessera-keys + mountPath: {{ .Values.node.tessera.keysPath }} + readOnly: true +{{- end }} + - name: data + mountPath: {{ .Values.node.tessera.dataPath }} + - name: tessera-peers + mountPath: /config/tessera-peers + ports: + - name: tessera + containerPort: {{ .Values.node.tessera.port }} + protocol: TCP + - name: tessera-tp + containerPort: {{ .Values.node.tessera.tpport }} + protocol: TCP + - name: tessera-q2t + containerPort: {{ .Values.node.tessera.q2tport }} + protocol: TCP + command: + - /bin/sh + - -c + args: + - | + exec + + cp {{ .Values.node.tessera.keysPath }}/tm.* {{ .Values.node.tessera.dataPath }}/ ; + + cat < {{ .Values.node.tessera.dataPath }}/tessera-config-09.json + { + "mode": "orion", + "useWhiteList": false, + "jdbc": { + "username": "sa", + "password": "", + "url": "jdbc:h2:{{ .Values.node.tessera.dataPath }}/db;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0", + "autoCreateTables": true + }, + "serverConfigs":[ + { + "app":"ThirdParty", + "enabled": true, + "serverAddress": "http://{{ include "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.node.tessera.tpport }}", + "communicationType" : "REST" + }, + { + "app":"Q2T", + "enabled": true, + "serverAddress": "http://{{ include "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.node.tessera.q2tport }}", + "sslConfig": { + "tls": "OFF" + }, + "communicationType" : "REST" + }, + { + "app":"P2P", + "enabled": true, + "serverAddress": "http://{{ include "besu-node.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.node.tessera.port }}", + "sslConfig": { + "tls": "OFF" + }, + "communicationType" : "REST" + } + ], + "peer": $$(cat /config/tessera-peers/tesseraPeers), + "keys": { + {{ if .Values.node.tessera.password }} + "passwordFile": "{{ .Values.node.tessera.passwordPath }}", + {{ end }} + "keyData": [ + { + "privateKeyPath": "/keys/tm.key", + "publicKeyPath": "/keys/tm.pub" + } + ] + }, + "alwaysSendTo": [] + } + EOF + + cat {{ .Values.node.tessera.dataPath }}/tessera-config-09.json + /tessera/bin/tessera -configfile {{ .Values.node.tessera.dataPath }}/tessera-config-09.json + +{{- end }} + + + - name: {{ .Release.Name }}-besu + image: {{ .Values.image.besu.repository }}:{{ .Values.image.besu.tag }} + imagePullPolicy: {{ .Values.image.besu.pullPolicy }} + resources: + requests: + cpu: "{{ .Values.node.besu.resources.cpuRequest }}" + memory: "{{ .Values.node.besu.resources.memRequest }}" + limits: + cpu: "{{ .Values.node.besu.resources.cpuLimit }}" + memory: "{{ .Values.node.besu.resources.memLimit }}" + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name +{{- if .Values.node.besu.envBesuOpts }} + - name: BESU_OPTS + value: "{{ .Values.node.besu.envBesuOpts }}" +{{- end }} +{{- if .Values.quorumFlags.usesBootnodes }} + - name: BESU_BOOTNODES + valueFrom: + configMapKeyRef: + name: besu-bootnodes + key: bootnodes-string +{{- end }} + volumeMounts: +{{- if and (ne .Values.cluster.provider "local") (.Values.cluster.cloudNativeServices) }} + - name: secrets-store + mountPath: {{ .Values.node.besu.keysPath }} + readOnly: true +{{- else }} + - name: besu-keys + mountPath: {{ .Values.node.besu.keysPath }} + readOnly: true +{{- if .Values.quorumFlags.privacy }} + - name: tessera-keys + mountPath: {{ .Values.node.besu.privacy.pubkeysPath }} + readOnly: true +{{- end }} +{{- end }} + - name: genesis + mountPath: /etc/genesis + readOnly: true + - name: static-nodes + mountPath: /config/static + - name: besu-config + mountPath: /etc/besu + readOnly: true + - name: data + mountPath: {{ .Values.node.besu.dataPath }} + ports: + - name: json-rpc + containerPort: {{ .Values.node.besu.rpc.port }} + protocol: TCP + - name: ws + containerPort: {{ .Values.node.besu.ws.port }} + protocol: TCP + - name: graphql + containerPort: {{ .Values.node.besu.graphql.port }} + protocol: TCP + - name: rlpx + containerPort: {{ .Values.node.besu.p2p.port }} + protocol: TCP + - name: discovery + containerPort: {{ .Values.node.besu.p2p.port }} + protocol: UDP + - name: metrics + containerPort: {{ .Values.node.besu.metrics.port }} + protocol: TCP + command: + - /bin/sh + - -c + args: + - | + exec + /opt/besu/bin/besu \ + --config-file=/etc/besu/config.toml \ + --Xdns-enabled=true --Xdns-update-enabled=true --Xnat-kube-service-name={{ include "besu-node.fullname" . }} \ + --min-gas-price=0 + + livenessProbe: + httpGet: + path: /liveness + port: 8545 + initialDelaySeconds: 180 + periodSeconds: 60 + volumes: + - name: genesis + configMap: + name: besu-genesis + items: + - key: genesis.json + path: genesis.json + - name: static-nodes + configMap: + name: besu-peers + items: + - key: static-nodes.json + path: static-nodes.json + - name: besu-config + configMap: + name: {{ include "besu-node.fullname" . }}-besu-config + +{{- if and (ne .Values.cluster.provider "local") (.Values.cluster.cloudNativeServices) }} + - name: secrets-store + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: {{ include "besu-node.fullname" . }}-secret-provider +{{- else }} + - name: besu-keys + secret: + secretName: {{ include "besu-node.fullname" . }}-keys +{{- if .Values.quorumFlags.privacy }} + - name: tessera-keys + secret: + secretName: {{ include "besu-node.fullname" . }}-tessera-keys +{{- end }} +{{- end }} +{{- if .Values.quorumFlags.privacy }} + - name: tessera-peers + configMap: + name: tessera-peers + items: + - key: tesseraPeers + path: tesseraPeers +{{- end }} +{{- if .Values.node.besu.permissions.enabled }} + - name: permissions-config + configMap: + name: {{ include "besu-node.fullname" . }}-permissions +{{- end }} diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-storage.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-storage.yaml new file mode 100644 index 00000000..5a22368f --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/node-storage.yaml @@ -0,0 +1,70 @@ +{{- if eq .Values.cluster.provider "azure" }} +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ include "besu-node.fullname" . }}-storage + namespace: {{ .Release.Namespace }} +provisioner: file.csi.azure.com # replace with "kubernetes.io/azure-file" if aks version is less than 1.21 +reclaimPolicy: {{ .Values.cluster.reclaimPolicy }} +allowVolumeExpansion: true +mountOptions: + - dir_mode=0755 + - file_mode=0755 + - uid=1000 + - gid=1000 + - mfsymlinks +parameters: + skuName: Standard_LRS + +{{- else if eq .Values.cluster.provider "aws" }} +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ include "besu-node.fullname" . }}-storage + namespace: {{ .Release.Namespace }} +provisioner: {{ .Values.storage.aws.provisioner }} +reclaimPolicy: {{ .Values.cluster.reclaimPolicy }} +allowVolumeExpansion: true +parameters: + type: {{ .Values.storage.aws.parameters.type }} + fsType: {{ .Values.storage.aws.parameters.fsType }} + +# --- +# apiVersion: storage.k8s.io/v1 +# kind: StorageClass +# metadata: +# name: {{ include "besu-node.fullname" . }}-storage +# namespace: {{ .Release.Namespace }} +# provisioner: efs.csi.aws.com +# reclaimPolicy: Retain +# parameters: +# provisioningMode: efs-ap +# fileSystemId: #your_file_system_id +# directoryPerms: "700" +# gidRangeStart: "1000" # optional +# gidRangeEnd: "2000" # optional +# basePath: "/dynamic_provisioning" # optional + +{{- else }} + +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ include "besu-node.fullname" . }}-storage + namespace: {{ .Release.Namespace }} + labels: + type: local +spec: + persistentVolumeReclaimPolicy: {{ .Values.cluster.reclaimPolicy }} + storageClassName: {{ include "besu-node.fullname" . }}-storage + capacity: + storage: "{{ .Values.storage.sizeLimit }}" + accessModes: + - ReadWriteOnce + hostPath: + path: "/tmp/{{ include "besu-node.fullname" . }}" + +{{- end }} diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/templates/permissions-configmap.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/permissions-configmap.yaml new file mode 100644 index 00000000..fc16a073 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/templates/permissions-configmap.yaml @@ -0,0 +1,20 @@ +{{- if .Values.node.besu.permissions.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "besu-node.fullname" . }}-permissions + labels: + app.kubernetes.io/name: besu-permissions + app.kubernetes.io/component: besu + app.kubernetes.io/part-of: {{ include "besu-node.fullname" . }} + app.kubernetes.io/namespace: {{ .Release.Namespace }} + app.kubernetes.io/release: {{ .Release.Name }} + app.kubernetes.io/managed-by: helm +data: + permissions_config.toml: |- + # Permissioning TOML file + + accounts-allowlist={{ .Values.node.besu.permissions.accounts.allowlist }} + nodes-allowlist={{ .Values.node.besu.permissions.nodes.allowlist }} + +{{- end -}} \ No newline at end of file diff --git a/src/eth/instance/infra/kubernetes/charts/besu-node/values.yaml b/src/eth/instance/infra/kubernetes/charts/besu-node/values.yaml new file mode 100644 index 00000000..e18a55f7 --- /dev/null +++ b/src/eth/instance/infra/kubernetes/charts/besu-node/values.yaml @@ -0,0 +1,158 @@ +--- + +quorumFlags: + privacy: false + # this will erase keys - so be careful with this on validators + removeKeysOnDelete: false + isBootnode: true # set this to true if this node is a bootnode + usesBootnodes: true # set this to true if the network you are connecting to use a bootnode/s that are deployed in the cluster + +cluster: + provider: local # choose from: local | aws | azure + cloudNativeServices: false # set to true to use Cloud Native Services (SecretsManager and IAM for AWS; KeyVault & Managed Identities for Azure) + reclaimPolicy: Delete # set to either Retain or Delete + +aws: + # the aws cli commands uses the name 'quorum-sa' so only change this if you altered the name + serviceAccountName: quorum-sa + # the region you are deploying to + region: ap-southeast-2 + +azure: + serviceAccountName: quorum-sa + # the clientId of the user assigned managed identity created in the template + identityClientId: azure-clientId + # the clientId of the user assigned managed identity in the node pool's resource group + nodePoolIdentityClientId: azure-clientId + keyvaultName: azure-keyvault + # the tenant ID of the key vault + tenantId: azure-tenantId + # the subscription ID to use - this needs to be set explicitly when using multi tenancy + subscriptionId: azure-subscriptionId + +storage: + sizeLimit: "20Gi" + pvcSizeLimit: "20Gi" + # NOTE: when you set this to Retain, the volume WILL persist after the chart is delete and you need to manually delete it + reclaimPolicy: "Delete" # choose from: Delete | Retain + aws: + provisioner: kubernetes.io/aws-ebs + parameters: + type: gp3 + fsType: ext4 + +# fixes permissions of volumes becuase besu runs as user `besu` and volumes prefer `root` +volumePermissionsFix: + - local + - aws + +node: + besu: + envBesuOpts: "" + resources: + cpuLimit: 0.7 + cpuRequest: 0.5 + memLimit: "2G" + memRequest: "1G" + # privKey: + # pubKey: + dataPath: "/data/besu" + keysPath: "/keys" + privateKeyPath: "/keys/nodekey" + genesisFilePath: "/etc/genesis/genesis.json" + logging: INFO + customLabels: {} + account: + password: 'password' + passwordPath: "/keys/accountPassword" + p2p: + enabled: true + host: "0.0.0.0" + port: 30303 + discovery: true + staticNodes: "/config/static/static-nodes.json" + maxPeers: 25 + rpc: + enabled: true + host: "0.0.0.0" + port: 8545 + api: '["DEBUG","ETH", "ADMIN", "WEB3", "IBFT", "NET", "TRACE", "EEA", "PRIV", "QBFT", "PERM", "TXPOOL"]' + corsOrigins: '["all"]' + authenticationEnabled: false + # Number of allowed active RPC connections for Besu node + maxActiveConnections: 80 + ws: + enabled: true + host: "0.0.0.0" + port: 8546 + api: '["DEBUG","ETH", "ADMIN", "WEB3", "IBFT", "NET", "TRACE", "EEA", "PRIV", "QBFT", "PERM", "TXPOOL"]' + authenticationEnabled: false + graphql: + enabled: false + host: "0.0.0.0" + port: 8547 + corsOrigins: '["all"]' + http: + allowlist: '["*"]' + metrics: + enabled: true + host: "0.0.0.0" + port: 9545 + # enable if using prometheus-stack metrics monitoring + serviceMonitorEnabled: false + metricsPush: + enabled: false + host: "5.5.5.5" + port: 9091 + interval: 15 + prometheusJob: "besu" + privacy: + url: "http://localhost:9101" + pubkeysPath: "/tessera" + pubkeyFile: "tm.pub" + onchainGroupsEnabled: false + permissions: + enabled: false + filePath: "" + nodes: + enabled: false + allowlist: ["enode://abcd..@1.2.3.3:30303","enode://efba..@1.2.3.4:besu-node-bootnode-1-0.besu-node-bootnode-1.besu.svc.cluster.local:30303"] + accounts: + enabled: false + allowlist: ["0x0000000000000000000000000000000000008888"] + nodesContract: + enabled: false + address: "0x0000000000000000000000000000000000009999" + accountsContract: + enabled: false + address: "0x0000000000000000000000000000000000008888" + + tessera: + resources: + cpuLimit: 1 + cpuRequest: 0.5 + memLimit: "2G" + memRequest: "1G" + tmkey: "" + tmpub: "" + password: "password" + passwordPath: "/keys/tm.password" + dataPath: "/data/tessera" + keysPath: "/keys" + port: 9000 + tpport: 9080 + q2tport: 9101 + +image: + besu: + repository: hyperledger/besu + tag: 24.7.1 + pullPolicy: IfNotPresent + tessera: + repository: quorumengineering/tessera + tag: 22.1.7 + pullPolicy: IfNotPresent + hooks: + repository: consensys/quorum-k8s-hooks + tag: qgt-0.2.15 + pullPolicy: IfNotPresent diff --git a/src/eth/model/type/network.type.ts b/src/eth/model/type/network.type.ts index 5baf2ffc..222a4995 100644 --- a/src/eth/model/type/network.type.ts +++ b/src/eth/model/type/network.type.ts @@ -14,7 +14,7 @@ export interface AllocType { * @requires alloc - [{@link AllocType} array] 原生代幣分配設定 */ export interface NetworkCreateType { - //TODO - networkType?: ? should be removed, after cluster is integrated + // TODO - networkType?: ? should be removed, after cluster is integrated networkType?: string chainId: number validatorNumber: number diff --git a/src/eth/model/yaml/helm-chart/genesisYaml.ts b/src/eth/model/yaml/helm-chart/genesisYaml.ts index 2a9555c1..eee00297 100644 --- a/src/eth/model/yaml/helm-chart/genesisYaml.ts +++ b/src/eth/model/yaml/helm-chart/genesisYaml.ts @@ -2,7 +2,7 @@ import HelmChartYaml from './helmChartYaml' import { NetworkType } from '../../../config/network.type' class GenesisConfigYaml extends HelmChartYaml { - public setGenesis(networkType: NetworkType, chainID: number, nodeCount: number) { + public setGenesis (networkType: NetworkType, chainID: number, nodeCount: number) { if (networkType === 'quorum') { this.setQuorumGenesis(chainID, nodeCount) } else if (networkType === 'besu') { @@ -12,7 +12,7 @@ class GenesisConfigYaml extends HelmChartYaml { } } - private setQuorumGenesis(chainID: number, nodeCount: number) { + private setQuorumGenesis (chainID: number, nodeCount: number) { this.setQuorumFlags({ privacy: false, removeKeysOnDelete: false, @@ -48,7 +48,7 @@ class GenesisConfigYaml extends HelmChartYaml { this.setService('rawGenesisConfig', genesisConfig) } - private setBesuGenesis(chainID: number, nodeCount: number) { + private setBesuGenesis (chainID: number, nodeCount: number) { const genesisConfig = { genesis: { config: { diff --git a/src/eth/model/yaml/helm-chart/helmChartYaml.ts b/src/eth/model/yaml/helm-chart/helmChartYaml.ts index c6ce439d..49fadc02 100644 --- a/src/eth/model/yaml/helm-chart/helmChartYaml.ts +++ b/src/eth/model/yaml/helm-chart/helmChartYaml.ts @@ -60,11 +60,11 @@ interface BesuNodeInterface { resources: { cpuLimit: number cpuRequest: number - memLimit: string - memRequest: string - } - account?: { - password: string + memLimit: string + memRequest: string + } + account?: { + password: string } } tessera?: { @@ -119,11 +119,10 @@ class HelmChartYaml extends BdkYaml { protected setQuorumFlags (quorumFlags: quorumFlags) { this.value.quorumFlags = quorumFlags } + protected setBesuFlags (besuFlags: besuFlags) { this.value.besuFlags = besuFlags } - - protected setCluster (cluster: ClusterInterface) { this.value.cluster = cluster diff --git a/src/eth/model/yaml/helm-chart/memberYaml.ts b/src/eth/model/yaml/helm-chart/memberYaml.ts index 42074d59..8296787d 100644 --- a/src/eth/model/yaml/helm-chart/memberYaml.ts +++ b/src/eth/model/yaml/helm-chart/memberYaml.ts @@ -2,7 +2,7 @@ import HelmChartYaml from './helmChartYaml' import { NetworkType } from '../../../config/network.type' class MemberConfigYaml extends HelmChartYaml { - public setMember(networkType: NetworkType, metrics = false) { + public setMember (networkType: NetworkType, metrics = false) { if (networkType === 'quorum') { this.setQuorumConfigs(metrics) } else if (networkType === 'besu') { @@ -39,7 +39,7 @@ class MemberConfigYaml extends HelmChartYaml { }) } - private setBesuConfigs(metrics = false) { + private setBesuConfigs (metrics = false) { this.setBesuFlags({ privacy: false, removeKeysOnDelete: false, diff --git a/src/eth/model/yaml/helm-chart/validatorYaml.ts b/src/eth/model/yaml/helm-chart/validatorYaml.ts index 2f8707ab..037ccdbe 100644 --- a/src/eth/model/yaml/helm-chart/validatorYaml.ts +++ b/src/eth/model/yaml/helm-chart/validatorYaml.ts @@ -2,7 +2,7 @@ import HelmChartYaml from './helmChartYaml' import { NetworkType } from '../../../config/network.type' class ValidatorConfigYaml extends HelmChartYaml { - public setValidator(networkType: NetworkType, metrics = false) { + public setValidator (networkType: NetworkType, metrics = false) { if (networkType === 'quorum') { this.setQuorumConfigs(metrics) } else if (networkType === 'besu') { @@ -12,7 +12,7 @@ class ValidatorConfigYaml extends HelmChartYaml { } } - private setQuorumConfigs(metrics = false) { + private setQuorumConfigs (metrics = false) { this.setQuorumFlags({ privacy: false, removeKeysOnDelete: false, @@ -35,7 +35,7 @@ class ValidatorConfigYaml extends HelmChartYaml { }) } - private setBesuConfigs(metrics = false) { + private setBesuConfigs (metrics = false) { this.setBesuFlags({ privacy: false, removeKeysOnDelete: false, diff --git a/src/eth/service/cluster.ts b/src/eth/service/cluster.ts index 20f2fceb..1d322944 100644 --- a/src/eth/service/cluster.ts +++ b/src/eth/service/cluster.ts @@ -6,8 +6,6 @@ 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' -import fs from 'fs' export default class Cluster extends AbstractService { /** @@ -33,7 +31,7 @@ export default class Cluster extends AbstractService { namespace: networkType, values: this.bdkFile.getGenesisChartPath(), }) as DockerResultType - const namespaceForJob = networkType === 'quorum' ? 'goquorum' : networkType; + const namespaceForJob = networkType === 'quorum' ? 'goquorum' : networkType await k8s.wait(`job.batch/${namespaceForJob}-genesis-init`, networkType) spinner.succeed(`Helm install genesis chart ${genesisOutput.stdout}`) // create network @@ -53,9 +51,7 @@ export default class Cluster extends AbstractService { } for (let i = 0; i < validatorNumber; i += 1) { spinner.start(`Helm install validator chart ${i + 1}`) - const valuesPath = this.bdkFile.getValidatorChartPath(i); - console.log(`Validator ${i + 1} values file content:`); - console.log(await fs.promises.readFile(valuesPath, 'utf8')); + const valuesPath = this.bdkFile.getValidatorChartPath(i) const validatorOutput = await k8s.install({ helmChart: networkType === 'quorum' ? this.bdkFile.getGoQuorumNodeChartPath() : this.bdkFile.getBesuNodeChartPath(), name: `validator-${i + 1}`, @@ -151,7 +147,7 @@ export default class Cluster extends AbstractService { } catch (error) { console.log(`Failed to delete release ${release} from quorum namespace:`) } - + try { await k8s.delete({ name: release, namespace: 'besu' }) } catch (error) { diff --git a/src/eth/service/network.ts b/src/eth/service/network.ts index 0bd1f0f5..1717f56a 100644 --- a/src/eth/service/network.ts +++ b/src/eth/service/network.ts @@ -74,7 +74,7 @@ export default class Network extends AbstractService { this.bdkFile.copyPrivateKeyToValidator(i) this.bdkFile.copyPublicKeyToValidator(i) this.bdkFile.copyAddressToValidator(i) - + validatorDockerComposeYaml.addValidator(bdkPath, i, 8545 + i * 2, networkCreateConfig.chainId, 30303 + i, networkCreateConfig.bootNodeList[i], staticNodesJson[i], networkType) this.createNetworkInfoJson(networkInfo, `http://validator${i}:${8545 + i * 2}`) } From 9d274162bdd6c7dc5f76fbdc0a01b757f4432613 Mon Sep 17 00:00:00 2001 From: marvin Date: Tue, 24 Sep 2024 15:47:23 +0800 Subject: [PATCH 6/6] fix: Add network type support and refactor network operations - Add NetworkType to network-related commands and services - Refactor network naming conventions throughout the codebase - Implement cluster deletion functionality - Update explorer, backup, and network command handlers - Modify Kubernetes runner and infrastructure interfaces - Adjust default network configuration and Kubernetes types --- src/eth/command/backup.ts | 2 +- src/eth/command/cluster.ts | 2 +- src/eth/command/cluster/apply.ts | 15 +++++----- src/eth/command/cluster/delete.ts | 28 +++++++++-------- src/eth/command/cluster/generate.ts | 16 +++++----- src/eth/command/explorer.ts | 2 +- src/eth/command/explorer/create.ts | 17 +++++++---- src/eth/command/explorer/delete.ts | 20 +++++++++---- src/eth/command/network.ts | 2 +- src/eth/command/network/add.ts | 8 ++--- src/eth/command/network/check.ts | 24 +++++++++++---- src/eth/command/network/create.ts | 2 +- src/eth/command/network/delete.ts | 2 +- src/eth/command/network/down.ts | 7 +++-- src/eth/command/network/generate.ts | 2 +- src/eth/command/network/get.ts | 4 +-- src/eth/command/network/join.ts | 11 +++---- src/eth/command/network/up.ts | 6 ++-- src/eth/config/network.type.ts | 2 +- .../instance/infra/InfraRunner.interface.ts | 2 ++ src/eth/instance/infra/kubernetes/runner.ts | 10 +++++++ src/eth/instance/kubernetesCluster.ts | 27 ++++++++++++++++- src/eth/model/defaultNetworkConfig.ts | 4 ++- src/eth/model/type/kubernetes.type.ts | 1 + src/eth/model/type/network.type.ts | 6 ++-- src/eth/service/cluster.ts | 30 +++++++++---------- src/eth/service/network.ts | 20 ++++++------- 27 files changed, 175 insertions(+), 97 deletions(-) diff --git a/src/eth/command/backup.ts b/src/eth/command/backup.ts index 880c52d8..0f2c5530 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 5cda8ba2..525f22b7 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 19b4525c..bc477f4b 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 b61d6582..04643bcf 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 37fe0405..e68fa94b 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 70c00bbf..355f9e3a 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 569926f6..c82048ba 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 82baa2e4..d102fe98 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 ebff5742..64a33da0 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 ebe506de..82b324a4 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 3a722e20..299095b2 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 381a92ed..7c48f3ab 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 58075c6d..d8cf9196 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 90484e5c..85b45406 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 fdac8b00..d7b5926f 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 e6be8b05..cfb0c570 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 cc936d99..ae035c5a 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 0ab69ee9..303c72b0 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 ba9499a0..9f8990f6 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 57463a84..923b250d 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 a6e2d369..86b3d2b3 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 22ae7fb6..b2e2c669 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 4474844e..0a84ccef 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 22d04f27..92e99c0f 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/model/type/network.type.ts b/src/eth/model/type/network.type.ts index 222a4995..98a25234 100644 --- a/src/eth/model/type/network.type.ts +++ b/src/eth/model/type/network.type.ts @@ -1,3 +1,5 @@ +import { NetworkType } from '../../config/network.type' + /** * @requires account - [string] wallet 地址 * @requires amount - [string] 分配原生代幣數量 @@ -14,8 +16,7 @@ export interface AllocType { * @requires alloc - [{@link AllocType} array] 原生代幣分配設定 */ export interface NetworkCreateType { - // TODO - networkType?: ? should be removed, after cluster is integrated - networkType?: string + networkType: NetworkType chainId: number validatorNumber: number memberNumber: number @@ -81,6 +82,7 @@ export interface GenesisJsonType { } export interface JoinNodeType { + networkType: any node: string ipAddress: string genesisJson: GenesisJsonType diff --git a/src/eth/service/cluster.ts b/src/eth/service/cluster.ts index 1d322944..4547cff3 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 1717f56a..85169da9 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 || NetworkType.QUORUM const genesisJsonYaml = new GenesisJsonYaml(networkType) genesisJsonYaml.addExtraData(extraData) genesisJsonYaml.addChainId(networkCreateConfig.chainId) @@ -75,7 +75,7 @@ export default class Network extends AbstractService { this.bdkFile.copyPublicKeyToValidator(i) this.bdkFile.copyAddressToValidator(i) - validatorDockerComposeYaml.addValidator(bdkPath, i, 8545 + i * 2, networkCreateConfig.chainId, 30303 + i, networkCreateConfig.bootNodeList[i], staticNodesJson[i], networkType) + validatorDockerComposeYaml.addValidator(bdkPath, i, 8545 + i * 2, networkCreateConfig.chainId, 30303 + i, networkCreateConfig.bootNodeList[i], staticNodesJson[i], networkType || NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://validator${i}:${8545 + i * 2}`) } this.bdkFile.createValidatorDockerComposeYaml(validatorDockerComposeYaml) @@ -94,7 +94,7 @@ export default class Network extends AbstractService { this.bdkFile.copyPublicKeyToMember(i) this.bdkFile.copyAddressToMember(i) - memberDockerComposeYaml.addMember(bdkPath, i, 8645 + i * 2, networkCreateConfig.chainId, 30403 + i, networkCreateConfig.bootNodeList[networkCreateConfig.validatorNumber + i], staticNodesJson[networkCreateConfig.validatorNumber + i], networkType) + memberDockerComposeYaml.addMember(bdkPath, i, 8645 + i * 2, networkCreateConfig.chainId, 30403 + i, networkCreateConfig.bootNodeList[networkCreateConfig.validatorNumber + i], staticNodesJson[networkCreateConfig.validatorNumber + i], networkType || NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://member${i}:${8645 + i * 2}`) } this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml) @@ -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 || NetworkType.QUORUM) 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 || NetworkType.QUORUM) 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 || NetworkType.QUORUM) 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 || NetworkType.QUORUM) this.createNetworkInfoJson(networkInfo, `http://member${i}:${8645 + i * 2}`) } this.bdkFile.createMemberDockerComposeYaml(memberDockerComposeYaml)